【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy
【题目大意】
P教授有编号为1...N的N件玩具,第i件玩具长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。如果将第i件玩具到第j个玩具放到一 个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关, 如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。求最小费用。
【思路】
懒得说了,把WC宋新波老师的课件搬运一下。
宋新波老师讲的很好,WC的时候第一次听斜率优化听他讲完秒懂了,时隔几个月再来消化一下。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int MAXN=50000+50; 8 int n,l; 9 int c[MAXN]; 10 LL s[MAXN],g[MAXN],x[MAXN],y[MAXN],f[MAXN]; 11 12 LL square(LL x) 13 { 14 return x*x; 15 } 16 17 double slop(int i,int j) 18 { 19 return ((y[j]-y[i])/(x[j]-x[i])); 20 } 21 22 void dp() 23 { 24 memset(f,0,sizeof(f)); 25 int head=0,tail=0; 26 int q[MAXN]; 27 q[head]=0; 28 for (int i=1;i<=n;i++) 29 { 30 y[i]=f[i-1]+square(x[i]); 31 while (head+1<tail && slop(q[tail-2],q[tail-1])>slop(q[tail-1],i)) tail--; 32 q[tail++]=i; 33 while (head+1<tail && slop(q[head],q[head+1])<2.0*g[i]) head++; 34 f[i]=f[q[head]-1]+square(g[i]-x[q[head]]); 35 } 36 } 37 38 void init() 39 { 40 scanf("%d%d",&n,&l); 41 memset(s,0,sizeof(s)); 42 for (int i=1;i<=n;i++) 43 { 44 scanf("%d",&c[i]); 45 s[i]=s[i-1]+c[i]; 46 g[i]=s[i]+i-l; 47 x[i]=s[i-1]+i; 48 } 49 } 50 51 void printans() 52 { 53 printf("%lld",f[n]); 54 } 55 56 int main() 57 { 58 init(); 59 dp(); 60 printans(); 61 return 0; 62 }