HDOJ3516-动态规划,四边形不等式优化

/*
此题和石子合并很相似。
DP方程: 
dp[i][j]=min{dp[i][k]+dp[k+1][j]+x[k+1]-x[i]+y[k]-y[j]}(i<=k<j)
其中dp[i][j]表示合并i到j的点最小树枝长度
根据题目的特点,对于点来说,只向左或向下合并,要知道的是i~j合并后生成新的一点,
此点与i~j的合并方法无关,坐标一定为(x[i],y[j]),每次只能合并两个相邻的点,
合并的代价是坐标差,所以有如上dp方程,边境值:dp[i][i]=0,(1<i<=n)。
到此得时间复杂度为O(n^3)的dp算法
使用四边形不等式优化后得O(n^2)的dp算法,见代码
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int NN=1001;
const int INF=0x3fffffff;
int n,x[NN],y[NN],dp[NN][NN],p[NN][NN];

int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        for (int i=1; i<=n; i++)
        {
            scanf("%d%d",x+i,y+i);
            dp[i][i]=0;
            p[i][i]=i;
        }
        p[n][n]=n-1;
        for (int l=1; l<n; l++)
        {
            for (int i=1; i<=n-l; i++)
            {
                int j=i+l;
                dp[i][j]=INF;
                for (int k=p[i][j-1]; k<=p[i+1][j]; k++)
                {
                    if (dp[i][j]>dp[i][k]+dp[k+1][j]+x[k+1]-x[i]+y[k]-y[j])
                    {
                        dp[i][j]=dp[i][k]+dp[k+1][j]+x[k+1]-x[i]+y[k]-y[j];
                        p[i][j]=k;
                    }
                }
            }
        }
        printf("%d\n",dp[1][n]);
    }
    return 0;
}

你可能感兴趣的:(算法,优化)