hdu 2829 斜率DP
思路:dp[i][x]=dp[j][x-1]+val[i]-val[j]-sum[j]*sum[i]+sum[j]*sum[j];
其中val[i]表示1~~i是一段的权值。
然后就是普通斜率dp做法。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cstring> #define Maxn 1010 #define LL __int64 using namespace std; LL dp[Maxn][Maxn],num[Maxn],sum[Maxn],val[Maxn]; int que[Maxn*10]; LL getleft(int x,int j,int k) { return dp[j][x]-val[j]+sum[j]*sum[j]-(dp[k][x]-val[k]+sum[k]*sum[k]); } LL getright(int j,int k) { return sum[j]-sum[k]; } int main() { int n,m,i,j,head,rear; while(scanf("%d%d",&n,&m)!=EOF,n||m){ memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++){ scanf("%I64d",num+i); sum[i]=sum[i-1]+num[i]; } for(i=1;i<=n;i++){ val[i]=val[i-1]+num[i]*sum[i-1]; dp[i][0]=val[i]; } for(j=0;j<m;j++){ head=1,rear=0; que[++rear]=j; for(i=j+1;i<=n;i++){ while(head<rear&&getleft(j,que[head+1],que[head])<sum[i]*getright(que[head+1],que[head])) head++; dp[i][j+1]=dp[que[head]][j]+val[i]-val[que[head]]-sum[que[head]]*sum[i]+sum[que[head]]*sum[que[head]]; while(head<rear&&getleft(j,i,que[rear])*getright(que[rear],que[rear-1])<=getleft(j,que[rear],que[rear-1])*getright(i,que[rear])) rear--; que[++rear]=i; } } printf("%I64d\n",dp[n][m]); } return 0; }