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 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...
随机推荐
- asp.net 错误 类型"xxxxx"同时存在于"xxx.dll"和"xxxx.dll" 中
http://walttoney.blog.163.com/blog/static/127685797201051112839328/错误 类型“System.Web.UI.ScriptManager ...
- 标准C程序设计七---20
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- iOS 取应用版本
// 应用网址 返回字典中有多种数据 NSString *urlString2 = [NSString stringWithFormat: @"%@", @"http: ...
- CKeditor如何实现图片上传功能
http://makaiyuan.blog.51cto.com/5819595/1049521 如何在数据库中导入excel文件内的数据:http://jingyan.baidu.com/album/ ...
- sgu 102模拟欧拉函数
感觉自己弱爆了,做做SGU吧... #include<iostream> #include<cmath> //欧拉函数 using namespace std; int eul ...
- JQuery select 编程时选中原有的值
js 此为核心代码 $(document).ready(function(){ $("#carTypeId").attr("value",'${carInfo. ...
- Chrome查看DNS状态提示:DNS pre-resolution and TCP pre-connection is disabled.
chrome://dns 别试了,在这个功能在旧版可以通过关闭预读可以实现,但是新版的不行. 但是可以通过这种方式替代: chrome://net-internals/#dns 这个方式更直观,可以看 ...
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存 ...
- 高性能JS-DOM
用脚本进行DOM操作的代价是很昂贵的,它是富web应用中最常见的性能瓶颈.主要有以下三种问题: 访问和修改DOM元素 修改DOM元素的样式导致repaint和reflow 通过DOM事件处理与用户进行 ...
- Intel Edision —— 从SSH无法连接到systemd
前言 原创文章,转载引用务必注明链接.如有疏漏,欢迎斧正. 最近在试用Wyliodrin,安装过程中出现了两个问题,一是无法使用SSH登录到Edison:二是EDISON磁盘的问题.分别涉及到syst ...