斜率DP hdu 3507
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.
大致题意:要打印一长串词语,每个词语有一个对应的打印费用Ci,要给词语分行,一行的总费用记为
,M是给定的常数
要求计算一种分行方案使得总费用最小。
数据规模50万。
分析:首先可以想到枚举上一次断行处,这样可以得到最初的状态转移方程:
,复杂度为O(n^2)。
观察一下数据规模为50万,需要优化。
主要思路是考虑淘汰肯定对最优答案没有贡献的点。
将状态转移方程展开:
(注:公式和图来自BIG YAO学长)

移项可得:


观察到蓝色字体部分只与j有关,绿色字体对给定的i为常量,红色字体部分取最小的时候dp[i]取最小。
将蓝色字体视为y(j),sum[j]视为x(j),问题就转化为对平面上无数个点(x,y),对每一个i,找出一个最优点(x0,y0),使得一条通过该点,斜率为k=2sum[i]的直线的截距最小。
放张图表现一下优化情况:

维护一个队列,即为下凸折线上点的队列,每次寻找最优的j的时候只在队列里的点找。(注意取得最优点的时候相邻的两根折线的斜率对于k=2sum[i]一大一小)
以下具体讨论怎么实现:
i不断向前推进,每次循环做两件事情:
1,找出对于dp[i]最优的上一个断行处j
如果队列上该点i和他后面的那个店形成的斜率小于k=2*sum[i]就头指针+1。
注意由于随i的递增,k=2*sum[i]必然递增,所以出队的点就不需要回来了
2,把i放入队列后就不再需要的点淘汰掉:

一旦出现3个点呈这样,即可淘汰点2,因为:直线经过点4的截距必然小于经过点2的截距,而经过点4的截距必然小于经过点1或点3的截距。
从而经过点2的截距必然小于小1或点3的截距,点2不可能为最优点,可淘汰。

然后把i放入队列(注意sum[i]为严格递增的,所以i个点中最后一个点必然在“外围”,不会被淘汰)
#include<cstdio>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int MAXN=;
long long int dp[MAXN],q[MAXN],sum[MAXN];
int n,m;
inline long long int getdp(int i,int j)
{
return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
}
inline long long int gety(int x,int y)
{
return dp[x]+sum[x]*sum[x]-dp[y]-sum[y]*sum[y];
}
inline long long int getx(int x,int y)
{
return *sum[x]-*sum[y];
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m)==)
{
sum[]=;
rep(i,,n)
{
scanf("%lld",&sum[i]);
sum[i]=sum[i-]+sum[i];
}
dp[]=;
int head,tail;
tail=;
head=;
q[tail]=; //虚拟制造一个点0,若0点最优代表把所有词语分成一行最优
rep(i,,n)
{
while(head+<=tail&&(gety(q[head+],q[head])<=sum[i]*getx(q[head+],q[head]))) head++; //寻找对于i最好的上一次分行的截止点
dp[i]=getdp(i,q[head]);
while(head+<=tail&&gety(i,q[tail])*getx(q[tail],q[tail-])<=gety(q[tail],q[tail-])*getx(i,q[tail])) tail--; //i放入队列后需要淘汰的点
q[++tail]=i; //把i放入队列
}
printf("%lld\n",dp[n]);
}
return ;
}
斜率DP hdu 3507的更多相关文章
- hdu 3507 斜率dp
不好理解,先多做几个再看 此题是很基础的斜率DP的入门题. 题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 设dp[i]表示输出前i个 ...
- hdu 3507 Print Article(斜率优化DP)
题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...
- 斜率dp A - Print Article HDU - 3507
A - Print Article HDU - 3507 今天刚刚学习了一下斜率dp,感觉还ok,主要就是要推这个斜率,然后利用数据结构来优化. 推荐两篇写的比较好的博客,https://www.cn ...
- HDU 3507 Print Article(斜率优化DP)
题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...
- HDU 3507 单调队列 斜率优化
斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...
- B - Lawrence HDU - 2829 斜率dp dp转移方程不好写
B - Lawrence HDU - 2829 这个题目我觉得很难,难在这个dp方程不会写. 看了网上的题解,看了很久才理解这个dp转移方程 dp[i][j] 表示前面1~j 位并且以 j 结尾分成了 ...
- HDU 3480 - Division - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- HDU 2829 - Lawrence - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 T. E. Lawrence was a controversial figure during ...
- HDU 2993 - MAX Average Problem - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 Consider a simple sequence which only contains p ...
随机推荐
- file_get_contents()实现get+post请求
先看file_get_contents()的定义: string file_get_contents ( string $filename [, bool $use_include_path = fa ...
- 奔跑在Docker上的Spark
转自:马踏飞燕--奔跑在Docker上的Spark 目录 为什么要在Docker上搭建Spark集群 网络拓扑 Docker安装及配置 ssh安装及配置 基础环境安装 Zookeeper安装及配置 H ...
- C++学习(五)入门篇——基本类型
面向对象编程的本质是设计并扩展自己的数据类型,让类型和数据匹配. 内置C++分成两种类型:基本类型和复合类型 1.简单变量 程序需要存储信息时,必须记录三个基本属性 (1)信息将存储在哪 (2)要存储 ...
- Mybatis JPA 代码构建
前段时间了解到Spring JPA,感觉挺好用,但其依赖于Hibernate,本人看到Hibernate就头大(不是说Hibernate不好哈,而是进阶太难),于是做了一个迷你版的Mybatis JP ...
- hadoop环境中误删除tmp文件夹的恢复
情景描述: 种种原因,不小心把系统根目录中的tmp文件删除了!发现jps之后看不到 master主机上面的namenode,resourcemanager,secondarynamenode三个进程了 ...
- ICMP--ping--Traceroute
ICMP经常被认为是IP层的一个组成部分.它传递差错报文以及其他需要注意的信息. ICMP报文通常被IP层或更高层协议TCP或UDP使用. 一些ICMP报文把差错报文返回给用户进程 ICMP报文是 ...
- JavaScript语言精粹-读书笔记
前言:很久之前读过一遍该书,近日得闲,重拾该书,详细研究一方,欢迎讨论指正. 目录: 1.精华 2.语法 3.对象 4.函数 5.继承 6.数组 7.正则表达式 8.方法 9.代码风格 10.优美的特 ...
- (转载)ubuntu创建新用户并增加管…
问题导读: 1.adduser与useradd有什么区别? 2.那种方式会自动创建组.用户组等信息? 3.如何新建用户具有管理员权限? $是普通管员,#是系统管理员,在Ubuntu下,root用户默认 ...
- Hardcoded string XXX,&…
eclipse布局文件警告:Hardcoded string XXX, should use @string resource
- 刚装的系统C盘占空间特别大怎么办?关闭win7的系统还原和调整虚拟内存
刚装的win7系统,C盘占空间特别大,清理垃圾,清理碎片之后还是特别大,检查一下,系统才20G,C盘却占用了40G,其实是没有关闭系统还原,再就是没有调整虚拟内存.win7旗舰版(其他版本也可能这样, ...