hdu 3507(DP+斜率优化)
Print Article
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 6653 Accepted Submission(s): 2054
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.
我们首先假设在算 dp[i]时,k<j ,j点比k点优。
也就是
dp[j]+(sum[i]-sum[j])^2+M <= dp[k]+(sum[i]-sum[k])^2+M;
所谓j比k优就是DP方程里面的值更小
对上述方程进行整理很容易得到:
[(dp[j]+sum[j]*sum[j])-(dp[k]+sum[k]*sum[k])] / 2(sum[j]-sum[k]) <=sum[i].
注意整理中要考虑下正负,涉及到不等号的方向。
左边我们发现如果令:yj=dp[j]+sum[j]*sum[j] xj=2*sum[j]
那么就变成了斜率表达式:(yj-yk)/(xj-xk) <= sum[i];
而且不等式右边是递增的。
所以我们可以看出以下两点:我们令g[k,j]=(yj-yk)/(xj-xk)
第一:如果上面的不等式成立,那就说j比k优,而且随着i的增大上述不等式一定是成立的,也就是对i以后算DP值时,j都比k优。那么k就是可以淘汰的。
如果不成立,那就说明k比j优,但是随着i的增加sum[i]增加,j始终会替换掉k.
第二:如果 k<j<i 而且 g[k,j]>g[j,i] 那么 j 是可以淘汰的。
假设 g[j,i]<sum[i]就是i比j优,那么j没有存在的价值
相反如果 g[j,i]>sum[i] 那么同样有 g[k,j]>sum[i] 那么 k比 j优 那么 j 是可以淘汰
所以这样相当于在维护一个下凸的图形,斜率在逐渐增大。
通过一个队列来维护。
初始化队列:head=0,tail=0;que[tail++]=0;表示tail处不存决策。
于是对于这题我们对于斜率优化做法可以总结如下:
1,用一个单调队列来维护解集。
2,假设队列中从头到尾已经有元素a b c。那么当d要入队的时候,我们维护队列的上凸性质,即如果g[d,c]<g[c,b],那么就将c点删除。直到找到g[d,x]>=g[x,y]为止,并将d点加入在该位置中。
3,求解时候,从队头开始,如果已有元素a b c,当i点要求解时,如果g[b,a]<sum[i],那么说明b点比a点更优,a点可以排除,于是a出队。最后dp[i]=getDp(q[head]);
#include <iostream>
#include <cstdio>
#include <string.h>
#include <math.h>
#define maxn 500010
#define LL int
using namespace std; LL sum[maxn],dp[maxn];
int que[maxn];
int head,tail;
int n;
LL m;
int getdp(int i,int j)
{
return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
} int getup(int j,int k) //yj-yk部分
{
return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]);
}
int getdown(int j,int k)
{
return *(sum[j]-sum[k]);
} void solve()
{
head=;
tail=;
que[tail++]=; //队列里存储的是决策 //tail处不存决策
for(int i=;i<=n;i++)
{
//从头开始找当前状态的最优决策,g[que[head+1],que[head]] < sum[i],说明que[head+1]比que[head]更优,删除que[head]
while(head+ < tail && getup(que[head+],que[head]) <= getdown(que[head+],que[head]) * sum[i] )
head++; //注意写成相乘,不然要考虑除数是否为负数
dp[i]=getdp(i,que[head]); //从尾往前,加入当前状态,如果g[i,que[tail]] < g[que[tail],que[tail-1]] ,可以排除que[tail]
/* while(head+1 <tail && getup(i,que[tail-1]) * getdown(que[tail-1],que[tail-2]) <= getup(que[tail-1],que[tail-2])*getdown(i,que[tail-1])))
{
tail--; //看到为什么RE了吗?笨蛋,括号打错了
}*/
while(head+<tail && getup(i,que[tail-])*getdown(que[tail-],que[tail-])<=getup(que[tail-],que[tail-])*getdown(i,que[tail-]))
tail--;
que[tail++]=i;
}
/*for(int i=1;i<=n;i++)
printf("%.0lf ",dp[i]);*/
printf("%d\n",dp[n]);
}
int main()
{ while(scanf("%d%d",&n,&m)==)
{
// init();
sum[]=;
for(int i=;i<=n;i++)
{
scanf("%d",&sum[i]);
sum[i]+=sum[i-];
}
//for(int i=1;i<=n;i++)
// printf("%lf ",sum[i]);
solve();
}
return ;
}
hdu 3507(DP+斜率优化)的更多相关文章
- HDU 3480 DP+斜率优化
题意:给你n个数字,然后叫你从这些数字中选出m堆,使得每一堆的总和最小,一堆的总和就是这一堆中最大值减去最小值的平方,最后要使得所有堆加起来的总和最小. 思路:对这些数字排序之后,很容易想到DP解法, ...
- Print Article hdu 3507 一道斜率优化DP 表示是基础题,但对我来说很难
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU 3480 DP 斜率优化 Division
把n个数分成m段,每段的值为(MAX - MIN)2,求所能划分得到的最小值. 依然是先从小到大排个序,定义状态d(j, i)表示把前i个数划分成j段,所得到的最小值,则有状态转移方程: d(j, i ...
- HDU 3045 DP 斜率优化 Picnic Cows
题意:将n个数分成若干组,每组数字的个数不少于t个,要把每组的数字减小到这组最小值,求所有数字减少的最小值. 先将这n个数从小到大排个序,可以想到一组里面的数一定是排序后相邻的. 设d(i)表示前i个 ...
- HDU 3507 [Print Article]DP斜率优化
题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...
- hdu 2829 Lawrence(斜率优化DP)
题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...
- 【BZOJ-4518】征途 DP + 斜率优化
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 230 Solved: 156[Submit][Status][ ...
- 【BZOJ-3437】小P的牧场 DP + 斜率优化
3437: 小P的牧场 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 705 Solved: 404[Submit][Status][Discuss ...
- 【BZOJ-1010】玩具装箱toy DP + 斜率优化
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 8432 Solved: 3338[Submit][St ...
随机推荐
- HDU 4821 字符串hash
题目大意: 希望找到连续的长为m*l的子串,使得m个l长的子串每一个都不一样,问能找到多少个这样的子串 简单的字符串hash,提前预处理出每一个长度为l的字符串的hash值 #include < ...
- [luoguP1866]滑动窗口(单调队列)
传送门 可以搞2个单调队列. 然后,然后就没有然后了. # include <iostream> # include <cstdio> # include <cstrin ...
- poj 3678 XOR和OR和AND(简单2-sat问题)
/* 题意:给你一些边,每条边有一个值和一个运算符XOR OR AND求是否存在一些点使得所有的边根据这些运算符 可以符合条件的权值. 建边方式参考:http://blog.csdn.net/shua ...
- 【设计模式】GOF设计模式趣解(23种设计模式)
创建型模式 1.FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说 ...
- hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]
传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...
- 【转载】ubuntu16.04 无线/Wifi 上网速度慢的解决方法
原文链接:http://tieba.baidu.com/p/4737599703[侵删] 一直以为是域名解析的问题,可也觉得不像.今天在百度搜索“ubuntu16.04域名解析慢”的时候无意中看到了h ...
- [Bzoj3209]花神的数论题(数位dp)
3209: 花神的数论题 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2633 Solved: 1182[Submit][Status][Disc ...
- java 返回json数据
Student st1 = new Student(1, "dg", 18, new Date()); Student st2 = new Student(2 ...
- Python第五讲
一.冒泡算法 1.将两个变量的值互换 a1 = 123 a2 = 456 #要想将a1与a2的值进行位置互换需要借助一个中间变量(temp) temp = a1#将a1的值赋值给temp(temp=1 ...
- (void __user *)arg 中__user的作用
__user宏简单告诉编译器(通过 noderef)不应该解除这个指针的引用(因为在当前地址空间中它是没有意义的). (void __user *)arg 指的是arg值是一个用户空间的地址,不能直接 ...