HDU3507 Print Article —— 斜率优化DP
题目链接:https://vjudge.net/problem/HDU-3507
Print Article
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 14899 Accepted Submission(s): 4648
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.
5
9
5
7
5
题意:
给出一段字符串,每个位置上的字符都有其相应的价值Ci。将字符串分成若干子串,且每个子串的价值为sigma(Ci)^2+M,i的范围为区间的范围。问怎样分割能得到最小的价值?
题解:
动态规划问题,设dp[i]为前i个字符的最小价值。再设sum[i]为前i个字符的价值前缀和。
可得:dp[i] = min( dp[j] + (sum[i]-sum[j])^2 + M ) ) , 其中 0<=k<=i-1。
整理:dp[i] = min( dp[j] + sum[i]^2 + sum[j]^2 - 2*sum[i]*sum[j] + M ), 其中 0<=j<=i-1。
最直接的做法是枚举j,求得最小值。但是此题n的范围为5e5,O(n^2)肯定超时了,所以要借用斜率优化,其方法是尽量排除掉那些不可能取得最优值的点,缩小状态转移的范围。推理如下:
1.如果 k<j,假设dp[i]在j处取得的值比k处取得的值要小,即更优,那么就有:
dp[j] + sum[i]^2 + sum[j]^2 - 2*sum[i]*sum[j] + M < dp[k] + sum[i]^2 + sum[k]^2 - 2*sum[i]*sum[k] + M,
整理得:[ (dp[j] + sum[j]^2) - (dp[k] + sum[k]^2) ] / ( 2*sum[j] - 2*sum[k] ) < sum[i]。
观察等式右边,可以看出这是一个斜率表达式。
我们设 yj = dp[j] + sum[j]^2, xj = 2*sum[j] ,那么上式就变为:( yj - yk ) / ( xj - xk ) < sum[i] 。
可知 ( yj - yk ) / ( xj - xk ) 就是直线 j---k 的斜率g[j,k]。
所以:当k<j,且j比k更优时, g[j,k] < sum[i]。而且,因为sum[i]递增,所以j比k更优的结论,对于i以后的位置也合适。……结论1(此结论用于求出dp[i]的最优转移状态)
2.当k<j<i时, 如果g[i,j] <= g[j,k]时, j可以直接排除。 ………………结论2(此结论用于维护队列)
1) 当g[i,j] < sum[i]时, i比j更优, 所以排除j。
2) 当g[i,j] >= sum[i] 时, g[j, k] >= sum[i],表明k比j更优,所以排除j。
3.综上:只需维护一个队列,其两个相邻元素间所形成直线的斜率单调递增。
注意:
判断不等式的时候,由于避免整除除法的问题,把除法判断改成了乘法判断,但是要特别注意,移项是否为负数,如果为负数,那么不等式的方向就会发生变化。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXM = 1e5+;
const int MAXN = 5e5+; int dp[MAXN], sum[MAXN];
int q[MAXN];
int n, M; int getUp(int i, int j)
{
return (dp[i]+sum[i]*sum[i]) - (dp[j]+sum[j]*sum[j]);
} int getDown(int i, int j)
{
return *(sum[i]-sum[j]);
} int getDp(int i, int j)
{
return dp[i] = dp[j] + (sum[i]-sum[j])*(sum[i]-sum[j]) + M;
} int main()
{
while(scanf("%d%d", &n, &M)!=EOF)
{
sum[] = ;
for(int i = ; i<=n; i++)
scanf("%d", &sum[i]), sum[i] += sum[i-]; dp[] = ;
int head = , tail = ;
q[tail++] = ;
for(int i = ; i<=n; i++)
{
//以下为寻找最优的转移状态。由于除法改成了乘法,所以顺序不能任意,否则不等号方向会改变。
while(head+<tail && getUp(q[head+], q[head])<sum[i]*getDown(q[head+], q[head])) head++;
dp[i] = getDp(i, q[head]);
//以下为维护队列
while(head+<tail && getUp(i, q[tail-])*getDown(q[tail-], q[tail-])<=
getUp(q[tail-], q[tail-])*getDown(i, q[tail-]) ) tail--;
q[tail++] = i;
} printf("%d\n", dp[n]);
}
}
HDU3507 Print Article —— 斜率优化DP的更多相关文章
- HDU3507 Print Article(斜率优化dp)
前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...
- hdu3507 Print Article[斜率优化dp入门题]
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- [hdu3507 Print Article]斜率优化dp入门
题意:需要打印n个正整数,1个数要么单独打印要么和前面一个数一起打印,1次打印1组数的代价为这组数的和的平方加上常数M.求最小代价. 思路:如果令dp[i]为打印前i个数的最小代价,那么有 dp[i] ...
- HDU3507 Print Article (斜率优化DP基础复习)
pid=3507">传送门 大意:打印一篇文章,连续打印一堆字的花费是这一堆的和的平方加上一个常数M. 首先我们写出状态转移方程 :f[i]=f[j]+(sum[i]−sum[j])2 ...
- hdu 3507 Print Article(斜率优化DP)
题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...
- Print Article /// 斜率优化DP oj26302
题目大意: 经典题 数学分析 G(a,b)<sum[i]时 a优于b G(a,b)<G(b,c)<sum[i]时 b必不为最优 #include <bits/stdc++.h& ...
- hdu 3507 Print Article —— 斜率优化DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507 设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m ...
- hdu3507Print Article(斜率优化dp)
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU-3507Print Article 斜率优化DP
学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...
随机推荐
- bzoj3609 [Heoi2014]人人尽说江南好 博弈
[Heoi2014]人人尽说江南好 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 581 Solved: 420[Submit][Status][D ...
- bzoj1975: [Sdoi2010]魔法猪学院【k短路&A*算法】
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2446 Solved: 770[Submit][Statu ...
- Tomcat 7 的domain域名配置,Tomcat 修改JSESSIONID
https://blog.csdn.net/catoop/article/details/64581325
- 表单form-input标签禁止聚焦输入
1.input标签禁止聚焦输入(针对小程序) <input type="text" disabled /> input标签禁止聚焦输入(针对网页html) 1).< ...
- Cookie 和 Session 有什么区别呢?
Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等 但如果再往深入探讨的话,就慢慢有一些朋友不太了解了 ...
- ros使用罗技f710无线控制手柄
参考:blog.csdn.net/hcx25909/article/details/9042469 罗技F710无线控制手柄ROS下使用说明 安装手柄相关的包和驱动 sudo apt-get inst ...
- Windows下配置scrapy需要MVC的14.0版本(转载)
转载于--http://blog.csdn.net/MrWilliamVs/article/details/77130965 杨煜冬煜杨的博客,他的博客比较杂,Java.Python都有--http: ...
- 精通python网络爬虫之自动爬取网页的爬虫 代码记录
items的编写 # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentati ...
- ueditor整合之后前段不显示高亮
自己整合ueditor插件后,发现在前段显示的时候并没有高亮处理 在网上看了一些方法后,自己尝试了下. 1.在页面上引入相关的js和css文件 主要是以下两个文件 <script src=&qu ...
- 将文件从已Root Android手机中copy出来的几个cmd窗口命令
将文件从已Root Android手机中copy出来的几个cmd窗口命令: 以shell身份登录adbadb shell进入adb后切换至root用户su更改文件的所属chown shell *更改文 ...