HDU3507 Print Article
来源:互联网 发布:酒店软件系统排名 编辑:程序博客网 时间:2024/05/17 03:55
Print Article
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 9231 Accepted Submission(s): 2878
Problem Description
One day Zero want to print an article which has N words, and each word i has a cost Ci to be printed. Also, Zero know that print k words in one line will cost
M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly.
Input
Output
Sample Input
5 559575
Sample Output
230
Author
Source
Recommend
此题是很基础的斜率DP的入门题。题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M让我们求这个费用的最小值。设dp[i]表示输出前i个的最小费用,那么有如下的DP方程:dp[i]= min{ dp[j]+(sum[i]-sum[j])^2 +M } 0<j<i
其中 sum[i]表示数字的前i项和。相信都能理解上面的方程。直接求解上面的方程的话复杂度是O(n^2)对于500000的规模显然是超时的。下面讲解下如何用斜率优化DP使得复杂度降低一维。
我们首先假设在算 dp[i]时,k<j ,j点比k点优。也就是dp[j]+(sum[i]-sum[j])^2+M <= dp[k]+(sum[i]-sum[k])^2+M;所谓j比k优就是DP方程里面的值更小.对上述方程进行整理很容易得到:[(dp[j]+sum[j]*sum[j])-(dp[k]+sum[k]*sum[k])] / 2(sum[j]-sum[k]) <=sum[i].
注意整理中要考虑下正负,涉及到不等号的方向。左边我们发现如果令:yj=dp[j]+sum[j]*sum[j] xj=2*sum[j]那么就变成了斜率表达式:(yj-yk)/(xj-xk) <= sum[i];而且不等式右边是递增的。
所以我们可以看出以下两点:我们令g[k,j]=(yj-yk)/(xj-xk)
第一:如果上面的不等式成立,那就说j比k优,而且随着i的增大上述不等式一定是成立的,也就是对i以后算DP值时,j都比k优。那么k就是可以淘汰的。
第二:如果 k<j<i 而且 g[k,j]>g[j,i] 那么 j 是可以淘汰的。假设 g[j,i]<sum[i]就是i比j优,那么j没有存在的价值.相反如果 g[j,i]>sum[i] 那么同样有 g[k,j]>sum[i] 那么 k比 j优 那么 j 是可以淘汰的
所以这样相当于在维护一个下凸的图形,斜率在逐渐增大。通过一个队列来维护。
int head,tail,n,m;// dp[i]= min{ dp[j]+M+(sum[i]-sum[j])^2 };int getDP(int i,int j){ return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);}int getUP(int j,int k) //yj-yk部分{ return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]);}int getDOWN(int j,int k){ return 2*(sum[j]-sum[k]);}int main(){ while(scanf("%d%d",&n,&m)==2) { for(int i=1;i<=n;i++) scanf("%d",&sum[i]); sum[0]=dp[0]=0; for(int i=1;i<=n;i++) sum[i]+=sum[i-1]; head=tail=0; q[tail++]=0; for(int i=1;i<=n;i++) { //把斜率转成相乘,注意顺序,否则不等号方向会改变的 while(head+1<tail && getUP(q[head+1],q[head])<=sum[i]*getDOWN(q[head+1],q[head])) head++; dp[i]=getDP(i,q[head]); while(head+1<tail && getUP(i,q[tail-1])*getDOWN(q[tail-1],q[tail-2])<=getUP(q[tail-1],q[tail-2])*getDOWN(i,q[tail-1])) tail--; q[tail++]=i; } printf("%d\n",dp[n]); } return 0;}
关于程序算法艺术与实践更多讨论与交流,敬请关注本博客和新浪微博songzi_tea.
- hdu3507 Print Article
- HDU3507 Print Article
- HDU3507 Print Article
- HDU3507 Print Article
- HDU3507--Print Article(斜率优化DP)
- 斜率优化模板题 HDU3507:Print Article
- [HDU3507]Print Article(斜率优化dp)
- hdu3507 Print Article(斜率优化dp)
- hdu3507 Print Article(斜率优化dp)
- hdu3507 Print Article DP+斜率优化
- 【HDU3507】Print Article-DP斜率优化入门
- [hdu3507] Print Article DP斜率优化入门
- 【HDU3507】【斜率优化DP】Print Article题解
- #HDU3507#Print Article(DP+斜率优化)
- [hdu3507] Print Article(斜率优化dp)
- HDU3507 Print Article 【斜率优化DP】
- HDU3507 print article【斜率优化dp】
- hdu3507 Print Article 斜率优化dp
- Strlen在实际使用中的一点体会
- 隐藏状态栏
- Nightmare Ⅱ
- Android自定义BaseAdapter看看小动物们在说啥
- Android属性动画——实现灵动菜单效果
- HDU3507 Print Article
- 使用Flexible实现手淘H5页面的终端适配
- Yii2数据库查询有关的操作
- ORIGIN 9.0 拟合曲线延伸
- c++ 如何获取当前登录用户的名字
- Qt5 - 中文 - 常量中有换行符
- linux文件内容的复制与粘贴
- 数码问题_纪中1433_暴力
- view的frame高度根据键盘出现、消失改变