码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1160 (区间DP+四边形优化)

时间:2014-11-28 21:29:24      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   sp   for   on   2014   问题   log   

这个转移方程不好想,尤其是一段值的解是中间,不明觉厉。dp[i][j] 用i个邮局,覆盖前j个村庄的最小值。

还有就是区间dp的平行四边形优化,这个题的转移方程并不是“区间DP”,所以枚举状态要逆着(很花时间),且用一个邮局覆盖都是从0断开了相当于没有断开。

类比于石子归并,矩阵链乘等标准区间DP,其所需状态之前就已经获得,不用倒推


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=310;
const int INF=0x7fffffff;

int n,m;
int s[NN],dp[NN][NN],w[NN][NN],p[NN][NN];

void get_w()//求在i~j号村庄间建一个邮局的最小距离和
{
    for (int i=1; i<n; i++)
      for (int j=i+1; j<=n; j++)
      {
          if ((i+j)%2) w[i][j]=s[j]-s[(i+j)/2]*2+s[i-1];
          else         w[i][j]=s[j]-s[(i+j)/2]-s[(i+j)/2-1]+s[i-1];
      }
}

void get_dp()
{
    for (int i=1; i<=n; i++)
    {
        dp[1][i]=w[1][i];
        p[1][i]=0;//注意这里
    }
    for (int c=2; c<=m; c++)
    {
        p[c][n+1]=n;
        for (int i=n; i; i--)///这里倒着写,p[c][i+1]是取后面值
        {
            int tmp=INF,k;
            for (int j=p[c-1][i]; j<=p[c][i+1]; j++)
            {
                if (dp[c-1][j]+w[j+1][i]<tmp) tmp=dp[c-1][k=j]+w[j+1][i];
            }
            dp[c][i]=tmp;
            p[c][i]=k;
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    s[0]=0;
    int x;
    for (int i=1; i<=n; i++)
    {
        scanf("%d",&x);
        s[i]=s[i-1]+x;
    }
    get_w();
    get_dp();
    printf("%d",dp[m][n]);
    return 0;
}

//直线取石子问题的平行四边形优化:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
const int INF = 1 << 30;
const int N = 1005;

int dp[N][N];
int p[N][N];
int sum[N];
int n;

int getMinval()
{
    for(int i=1; i<=n; i++)
    {
        dp[i][i] = 0;
        p[i][i] = i;//这个自己跟自己乘自然是以自己为分割了。
    }
    for(int len=1; len<n; len++)
    {
        for(int i=1; i+len<=n; i++)
        {
            int end = i+len;
            int tmp = INF;
            int k = 0;
            for(int j=p[i][end-1]; j<=p[i+1][end]; j++)
            {
                if(dp[i][j] + dp[j+1][end] + sum[end] - sum[i-1] < tmp)
                {
                    tmp = dp[i][j] + dp[j+1][end] + sum[end] - sum[i-1];
                    k = j;
                }
            }
            dp[i][end] = tmp;
            p[i][end] = k;
        }
    }
    return dp[1][n];
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        sum[0] = 0;
        for(int i=1; i<=n; i++)
        {
            int val;
            scanf("%d",&val);
            sum[i] = sum[i-1] + val;
        }
        printf("%d\n",getMinval());
    }
    return 0;
}


POJ 1160 (区间DP+四边形优化)

标签:blog   io   os   sp   for   on   2014   问题   log   

原文地址:http://blog.csdn.net/gg_gogoing/article/details/41578121

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!