过不了样例(输出14)
附推导过程:
转移方程:
fi=minj=1i−1{fj+((i−(j+1)+sumi−sumj)−l)2}
若j,k为i的两个决策点,k<j<i,且j比k更优那么: fj+(i−j−1+sumi−sumj−l)2<fk+(i−k−1+sumi−sumk−l2)
定义g(i)=i+sumi,h(i)=i+sumi−l−1
fj+(h(i)−g(j))2<fk+(h(i)−g(k))2
fj−fk<(h(i)2+g(k)2−2⋅h(i)⋅g(k))−(h(i)2+g(j)2−2⋅h(i)⋅g(j))
fj−fk<g(k)2−g(j)2−2⋅h(i)⋅(g(k)−g(j))
fj−fk<(g(k)−g(j))(g(k)+g(j))−2⋅h(i)⋅(g(k)−g(j))
因为g(k)=k+sumk<j+sumk<j+sumj=g(j),所以除以g(k)−g(j)需要反号
g(k)−g(j)fj−fk>g(k)+g(j)−2⋅h(i)
g(k)−g(j)−(g(k)+g(j))(g(k)−g(j))+fj−fk>−2⋅h(i)
g(j)−g(k)fj+g(j)2−fk−g(k)2<2⋅h(i)
#include<stdio.h>
#define inf 1000000000
const int maxn=50005;
int i,j,k,m,n,L,l,r;
int c[maxn],sum[maxn],q[maxn],f[maxn];
inline int g(int p){
return p+sum[p];
}
inline int h(int p){
return p+sum[p]-L-1;
}
inline int x(int p){
return f[p]+g(p)*g(p);
}
inline int y(int p){
return g(p);
}
inline double slope(int a,int b){
if(x(a)==x(b))
return y(a)<=y(b)? 1.0*inf:-1.0*inf;
return 1.0*(y(a)-y(b))/(x(a)-x(b));
}
int main(){
scanf("%d%d",&n,&L);
for(i=1;i<=n;i++)
scanf("%d",&c[i]);
for(i=1;i<=n;i++)
sum[i]=sum[i-1]+c[i];
l=1,r=0,q[++r]=0;
for(i=1;i<=n;i++){
while(l<r&&slope(q[l+1],q[l])<=2.0*h(i))
l++;
f[i]=f[q[l]]+(h(i)-g(q[l]))*(h(i)-g(q[l]));
while(l<r&&slope(q[r],q[r-1])>=slope(i,q[r]))
r--;
q[++r]=i;
}
printf("%d\n",f[n]);
return 0;
}