f[i]=min(f[j]+w[j,i])+c[i]; j∈[0,i-1]
w[j,i]=p[j+1]*(x[i]-x[j+1])+...+p[i]*(x[i]-x[i]);
最裸的DP是n^2的,显然会超时
现在化简一下w[j,i]
w[j,i]=x[i]*(p[j+1]+...+p[i])-(x[j+1]*p[j+1]+...+x[i]*p[i]);
设sum[i]=sigma(p[j]*x[j]); sump[i]=sigma(p[j]); j∈[1,i]
那么 w[j,i]=-x[i]*(sump[i]-sump[j])-(sum[i]-sum[j])
=-x[i]*sump[j]+sum[j]+x[i]*sump[i]-sum[i];
即 f[i]=min(-x[i]*sump[j]+sum[j]+f[j])+x[i]*sum[i]-sum[i]; j∈[0,i-1]
注意到sump[j] 和 sum[j]+f[j] 是单调递增的,可以证明决策是单调向右的。
维护一个下凸包即可。
附 DP斜率优化参考教程
①:http://wenku.baidu.com/link?url=9JNX3KG-XtAljlg1JDOIvSN_t_UntKNFdi-mDgWOh-oUEIbFQDOStyKRKXxUILxZ1CQXBJNoPzKf23IHmLtNT65peiiBoxl9vDM-G6MPsJy
②:http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html
1 const maxn=1000008; 2 var q,f,x,p,c,sum,sump:array[0..maxn] of int64; 3 i,h,t,n:longint; 4 function kx(i,j:longint):int64; 5 begin 6 exit(sump[i]-sump[j]); 7 end; 8 function ky(i,j:longint):int64; 9 begin 10 exit(f[i]+sum[i]-f[j]-sum[j]); 11 end; 12 begin 13 readln(n); 14 for i:=1 to n do readln(x[i],p[i],c[i]); 15 for i:=1 to n do sump[i]:=sump[i-1]+p[i]; 16 for i:=1 to n do sum[i]:=sum[i-1]+p[i]*x[i]; 17 q[1]:=0; h:=1; t:=1; 18 for i:=1 to n do 19 begin 20 while (h<t) and (x[i]*kx(q[h+1],q[h])>ky(q[h+1],q[h])) do inc(h); 21 f[i]:=-x[i]*sump[q[h]]+f[q[h]]+sum[q[h]]+x[i]*sump[i]-sum[i]+c[i]; 22 while (h<t) and ( ky(i,q[t])*kx(q[t],q[t-1])<=ky(q[t],q[t-1])*kx(i,q[t])) do dec(t); 23 inc(t); 24 q[t]:=i; 25 end; 26 writeln(f[n]); 27 end.