hdu 2829 Lawrence (四边形不等式优化DP)

题目描述

传送门

题目大意:给出一个长度为n的序列,要求砍成m+1段,每段的权值是该区间中数的两两乘积之和,求划分的最小权值。

题解

预处理 w[i][j] 表示区间[i,j]中数的两两乘积之和
f[j][i]=min{f[k][i1]+w[k+1][j]}
这个式子和poj 1160的DP转移式是一样的,所以用同样的方式优化DP即可。

代码

#include
#include
#include
#include
#define N 1003
#define LL long long 
using namespace std;
const LL inf=1e13;
LL dp[N][N],w[N][N],val[N],squ[N];
int n,m,s[N][N];
int main()
{
    freopen("a.in","r",stdin);
    while (true) {
        scanf("%d%d",&n,&m); 
        if (!n&&!m) break;
        m++;
        memset(w,0,sizeof(w));
        memset(dp,0,sizeof(dp));
        for (int i=1;i<=n;i++) scanf("%I64d",&val[i]);
        for (int i=1;i<=n;i++) squ[i]=squ[i-1]+val[i]*val[i];
        for (int i=1;i<=n;i++) val[i]+=val[i-1];
        for (int i=1;i<=n;i++)
         for (int j=i;j<=n;j++) 
          w[i][j]=(val[j]-val[i-1])*(val[j]-val[i-1])-(squ[j]-squ[i-1]),w[i][j]/=2;
        for (int i=1;i<=n;i++)
         dp[i][1]=w[1][i],s[i][1]=0;
        for (int i=2;i<=m;i++) {
            s[n+1][i]=n;
            for (int j=n;j>i;j--) {
                dp[j][i]=inf;
                for (int k=s[j][i-1];k<=s[j+1][i];k++) {
                    LL tmp=dp[k][i-1]+w[k+1][j];
                    if (tmpprintf("%I64d\n",dp[n][m]);
    }
}

你可能感兴趣的:(图论)