5 5 5 9 5 7 5
230
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507
题意:给你n个单词,要你决定一个排版的策略使得花费最小,花费的公式在上面
分析:很容易的一道题,写出简单的转移
f[ i ]=min{ f[ j-1 ] +w[ j , i ] + m} (1<=j<=i)
w[ j , i ]=sum{ c[ j ] + c[ j+1 ] +... +c[ i ] }
设:s[ i ]=sum{ c[ 1 ] + c[ 2 ]+... + c[ i ] }
综上可以得到
f[ i ]=min{ f[ j-1 ]+s[ j-1 ]^2 -2 s[ i ]*s[ j-1 ] }+s[ i ]^2+m
令 a=2s[ i ] x=s[ j- 1] y= f[ j-1 ]+s[ j-1 ]^2
G=-ax+y
即y=ax+G,很明显的斜率优化了。。。
这题丝毫没有坑人的地方吧,1Y了
代码:
#include<cstdio> #include<iostream> using namespace std; const int mm=555555; int f[mm],s[mm],q[mm]; int i,j,n,m,l,r; bool TRight(int ax,int ay,int bx,int by,int cx,int cy) { return (ax-bx)*(cy-by)>=(ay-by)*(cx-bx); } int gx(int i) { return s[i-1]; } int gy(int i) { return f[i-1]+s[i-1]*s[i-1]; } int get(int i,int a) { return gy(i)-a*gx(i); } int main() { while(~scanf("%d%d",&n,&m)) { f[0]=s[0]=l=0,r=-1; for(i=1;i<=n;++i) { scanf("%d",&s[i]); s[i]+=s[i-1]; } for(i=1;i<=n;++i) { while(l<r&&TRight(gx(q[r-1]),gy(q[r-1]),gx(q[r]),gy(q[r]),gx(i),gy(i)))--r; q[++r]=i; while(l<r&&get(q[l],2*s[i])>=get(q[l+1],2*s[i]))++l; f[i]=get(q[l],2*s[i])+m+s[i]*s[i]; } printf("%d\n",f[n]); } return 0; }