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

大致题意:要打印一长串词语,每个词语有一个对应的打印费用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的更多相关文章

  1. hdu 3507 斜率dp

    不好理解,先多做几个再看 此题是很基础的斜率DP的入门题. 题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 设dp[i]表示输出前i个 ...

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

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

  3. 斜率dp A - Print Article HDU - 3507

    A - Print Article HDU - 3507 今天刚刚学习了一下斜率dp,感觉还ok,主要就是要推这个斜率,然后利用数据结构来优化. 推荐两篇写的比较好的博客,https://www.cn ...

  4. HDU 3507 Print Article(斜率优化DP)

    题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...

  5. HDU 3507 单调队列 斜率优化

    斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...

  6. B - Lawrence HDU - 2829 斜率dp dp转移方程不好写

    B - Lawrence HDU - 2829 这个题目我觉得很难,难在这个dp方程不会写. 看了网上的题解,看了很久才理解这个dp转移方程 dp[i][j] 表示前面1~j 位并且以 j 结尾分成了 ...

  7. HDU 3480 - Division - [斜率DP]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  8. HDU 2829 - Lawrence - [斜率DP]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 T. E. Lawrence was a controversial figure during ...

  9. HDU 2993 - MAX Average Problem - [斜率DP]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 Consider a simple sequence which only contains p ...

随机推荐

  1. JQuery学习笔记——层级选择器

    JQuery学习笔记--层级选择器 上一篇学习了基础的五种选择,分别是id选择器,class选择器,element选择器,*选择器 和 并列选择器.根据手册大纲,这篇学习的是层级选择器. 选择器: 1 ...

  2. FreeRTOS——中断管理

    1. 只有以“FromISR”或"FROM_ISR"结束的API函数或宏才可以在中断服务函数中使用. 2. 除互斥信号量外,所有类型的信号量都可以调用 xSemaphoreTake ...

  3. nyoj_2:括号配对问题

    模拟栈的操作,很基础的一道题 题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=2 #include<stdio.h> #inc ...

  4. 大三仍是Linux系统小白的我给大家讲讲学习历程

    我与Linux结缘是在大三的时候.我与Linux熟识是在偶然遇到<Linux就该这么学>的时候.因为我是电子信息工程专业,在高年级时开设了嵌入式课程,嵌入式系统是一种专用的计算机系统,作为 ...

  5. (转)Linux端口nmap和netstat命令

    场景:弄不清楚端口和服务的关系,总觉得这个命令很有用但是还不清楚如何使用 1 linux端口与服务 1.1 安全概述 网络传输安全.操作系统安全.应用软件安全构成了整个网络应用的安全:其中应用软件安全 ...

  6. 【SqlServer系列】集合运算

    1   概述 已发布[SqlServer系列]文章如下: [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [SqlS ...

  7. C指针1

    //定义:指针是一个特殊的数据类型,指针指向内存中的地址,因此,指针变量存储的是内存中的一个地址 //例子,%p表示打印一个地址,打印p表示打印p指向的地址 //输出结果为0x7fff5fbff7dc ...

  8. IT人不要一直做技术

    我现在是自己做,但我此前有多年在从事软件开发工作,当回过头来想一想自己,觉得特别想对那些初学JAVA/DOT.NET技术的朋友说点心里话,希望你们能从我们的体会中,多少受点启发(也许我说的不好,你不赞 ...

  9. 【原创】IE11惊现无厘头Crash BUG(三招搞死你的IE11,并提供可重现代码)!

    前言 很多人都知道我们在做FineUI控件库,而且我们也做了超过 9 年的时间,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅: 分享IE7一个神奇的BUG(不是封闭 ...

  10. centos7 Mysql备份还原并下载到windos

    数据库备份 1.show databases; #查看一下数据库 2.对应数据库做备份开始: mysqldump -u root -p 需要备份的数据库 >  db.sql     #把它备份到 ...