题目链接: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

Problem Description
Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate this degree.
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
There are many test cases. For each test case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines. Input are terminated by EOF.
 
Output
A single number, meaning the mininum cost to print the article.
 
Sample Input
5 5
5
9
5
7
5
 
Sample Output
230
 
Author
Xnozero
 
Source
 
Recommend
zhengfeng

题意:

给出一段字符串,每个位置上的字符都有其相应的价值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的更多相关文章

  1. HDU3507 Print Article(斜率优化dp)

    前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...

  2. hdu3507 Print Article[斜率优化dp入门题]

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  3. [hdu3507 Print Article]斜率优化dp入门

    题意:需要打印n个正整数,1个数要么单独打印要么和前面一个数一起打印,1次打印1组数的代价为这组数的和的平方加上常数M.求最小代价. 思路:如果令dp[i]为打印前i个数的最小代价,那么有 dp[i] ...

  4. HDU3507 Print Article (斜率优化DP基础复习)

    pid=3507">传送门 大意:打印一篇文章,连续打印一堆字的花费是这一堆的和的平方加上一个常数M. 首先我们写出状态转移方程 :f[i]=f[j]+(sum[i]−sum[j])2 ...

  5. hdu 3507 Print Article(斜率优化DP)

    题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...

  6. Print Article /// 斜率优化DP oj26302

    题目大意: 经典题 数学分析 G(a,b)<sum[i]时 a优于b G(a,b)<G(b,c)<sum[i]时 b必不为最优 #include <bits/stdc++.h& ...

  7. 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 ...

  8. hdu3507Print Article(斜率优化dp)

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  9. HDU-3507Print Article 斜率优化DP

    学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...

随机推荐

  1. cf615D Multipliers

    Ayrat has number n, represented as it's prime factorization pi of size m, i.e. n = p1·p2·...·pm. Ayr ...

  2. COdevs 1074 食物链

    1074 食物链 2001年NOI全国竞赛  时间限制: 3 s 空间限制: 64000 KB 题目等级 : 钻石 Diamond 题目描述 Description 动物王国中有三类动物 A,B,C, ...

  3. 玩转css样式选择器----当父元素有多个子元素时选中最后一个

  4. zoj 3812 We Need Medicine (dp 状压)

    先贴一下转载的思路和代码,,,:http://blog.csdn.net/qian99/article/details/39138329 状压dp博大精深啊,以后看到n<=50都可以往状压上想, ...

  5. [转发]Android 系统稳定性 - ANR(三)

    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之. 编写者:李文栋 http://rayleeya.iteye.com/blog/1956056 1. ...

  6. 如何查看项目的Laravel框架的版本

    如何查看项目的Laravel框架的版本 接触到一个已有的使用Laravel框架的项目时, 打开项目根目录下的composer.json文件, 找到 laravel/framework 的值,即可查看版 ...

  7. 隐藏video标签的下载按钮

    问题: 使用video标签时,有些浏览器会显示视频的下载按钮,而这并不是我们需要的功能,必须想办法去掉. 解决方法: 使用下面的css可以达到隐藏下载按钮的效果,但是点击下载的位置,还是能出现开始下载 ...

  8. 实现TTCP (检测TCP吞吐量)

    实现TTCP (检测TCP吞吐量) 应用层协议 为了解决TCP粘包问题以及客户端阻塞问题 设计的应用层协议如下: //告知要发送的数据包个数和长度 struct SessionMessage { in ...

  9. Django 中的时间处理

    操作系统为OS X 10.9.2,Django为1.6.5. 1.时区 在setting.py文件中设置了时区 TIME_ZONE = 'Asia/Shanghai' # 设置时区为UTC+8 USE ...

  10. ffmpeg 时间戳

    转http://blog.csdn.net/yfh1985sdq/article/details/5721953 AVpacket里的时间戳pts和dts.单位好像是us. 问 : 时间戳pts和dt ...