f[i][j] 表示到j为止,前面断了i条路的最小值;
dp方程:f [i][j]= min { f[i-1][k] + cost( k+1 , j ) } ( i <= k <= j-1 )
这是n^3的dp,可以用斜率优化为n^2; 主要是求出 cost( k+1 , j )的表达式。 求出表达式后就可以设出x和y以及斜率K; 判断一下x或者y是否单调,以及k是否单调。 然后就基本上是套模板了。
这题看网上说可以用四边形优化。还不了解四边形优化,先用斜率做了,等看了四边形再补上四边形的做法。
#include<stdio.h>
#define LL long long
typedef struct { LL x,y;}Node; Node pp[1010],tmp;
LL sum[1010];
LL w[1010];
LL f[1010][1010];
int a[1010];
int Xmul(Node a,Node b,Node c)
{
return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
}
int main()
{
int n,m,i,j,k,head,tail;
while( scanf("%d%d",&n,&m),n+m )
{
sum[0]=0; w[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",a+i);
sum[i]=a[i];
sum[i]+=sum[i-1];
w[i]=a[i]*sum[i];
w[i]+=w[i-1];
}
for(j=1;j<=n;j++) f[0][j]=sum[j]*sum[j]-w[j];
for(i=1;i<=m;i++)
{
head=1; tail=0;
for(j=i+1;j<=n;j++)
{
k=j-1;
tmp.x=sum[k]; tmp.y=f[i-1][k]+w[k];
while( head < tail && Xmul(pp[tail-1],pp[tail],tmp)<=0 )
tail--;
pp[++tail]=tmp;
while( head < tail && (double)(pp[head+1].y-pp[head].y) / (pp[head+1].x-pp[head].x) <= sum[j] )
head++;
f[i][j]= pp[head].y-pp[head].x*sum[j]+sum[j]*sum[j]-w[j];
}
}
printf("%I64d\n",f[m][n]);
}
return 0;
}