HDU3507 Print Article(斜率优化dp)
前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html
上面讲的很详细,但是实际上有些地方貌似是不小心写错了,所以我也来复述一下感悟一下收获。
首先题意是比较明确的,如果我们定义dp[i]为打印到第i个字符时的最小花费的话,显然有下面的转移:
dp[i]=dp[j]+(sum[i]-sum[j])^2+m
然后我们考虑k<j<i时的情况,如果说我们求dp[i]的时候选择j比选择k更优,就会有:
dp[j]+(sum[i]-sum[j])^2+m>dp[k]+(sum[i]-sum[k])^2+m
然后化简就会有:
(dp[j]+sum[j]^2)-(dp[k]-sum[k]^2)/2*(sum[j]-sum[k]) < sum[i]
然后左边的项看上去是非常像斜率的,所以我们可以定义一个g[j,k]=(dp[j]+sum[j]^2)-(dp[k]-sum[k]^2)/2*(sum[j]-sum[k])
g[j,k]<sum[i]就表示了j点比k点更优。
考虑a<b<c的情况 g[c,b]<g[b,a]的时候说明什么了呢??
如果g[c,b]<sum[c] 那么 c比b更优
如果g[c,b]>=sum[c],则g[b,a]>g[c,b]>=sum[c] 说明 a比b更优
所以如果(c,b)的斜率<(b,a)的斜率那么 b点是不用考虑的。
基于这一点我们可以用一个队列,像求凸包一样去维护可行的点集。由于g[c,b]<g[b,a]的情况不存在,所以只有g[c,b]>=g[b,a],因此点集应该是上凸的
所以对于队列一开始的点集,如果队首元素的斜率g(que[qh+1],que[qh])<sum[i]的话,那么我们可以将队首元素弹出
(其实一般情况下应该是不可以的,但由于sum[i]是递增的,所以在求dp[i]时有g(que[qh+1],que[qh])<sum[i],dp[i+1]也有g(que[qh+1],que[qh])<sum[i+1],因此队首的元素一定是不用考虑的)
然后直到我们找到一个可行解。
然后就将现在的元素插入队尾,插入队尾的时候就要维护下凸的性质,大概就是这样子。
原博客讲的十分的清楚,然后评论里也讲了一些存在的纰漏和补充的地方,原博的下凸应该改为上凸吧,还有就是弹队首的时候还是要多加说明可能会更好。
#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
using namespace std;#define ll long long
#define maxn 510000ll dp[maxn];
ll sum[maxn];
ll a[maxn];
int n, m;int que[maxn];
int qh, qt;ll getup(int i, int j){return (dp[i] + sum[i] * sum[i]) - (dp[j] + sum[j] * sum[j]);
}ll getdown(int i, int j){return 2 * (sum[i] - sum[j]);
}int main()
{while (cin >> n >> m){a[0] = sum[0] = 0;for (int i = 1; i <= n; ++i){scanf("%I64d", a + i);sum[i] = sum[i - 1] + a[i];}dp[0] = 0;qh = qt = 0;que[qt++] = 0;for (int i = 1; i <= n; ++i){while (qh + 1 < qt && getup(que[qh + 1], que[qh]) <= getdown(que[qh + 1], que[qh]) * sum[i]){qh++;}dp[i] = dp[que[qh]] + (sum[i] - sum[que[qh]])*(sum[i] - sum[que[qh]]) + m;while (qh + 1 < qt && getup(i, que[qt - 1])*getdown(que[qt - 1], que[qt - 2]) <= getup(que[qt - 1], que[qt - 2])*getdown(i, que[qt - 1])){qt--;}que[qt++] = i;}printf("%I64d\n", dp[n]);}return 0;
}
转载于:https://www.cnblogs.com/chanme/p/3891049.html
HDU3507 Print Article(斜率优化dp)相关推荐
- HDU3507 Print Article —— 斜率优化DP
题目链接:https://vjudge.net/problem/HDU-3507 Print Article Time Limit: 9000/3000 MS (Java/Others) Mem ...
- HDU-3507Print Article 斜率优化DP
学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...
- hdu3507 print article
hdu3507 print ariticle 斜率优化入门题 一个人要用n\((0\le n\le 500005)\)个单词打一篇文章.一个单词有一个价值\(C_i\),一个文章可以分成若干段,每一段 ...
- HDU 3507 Print Article(斜率优化DP)
题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...
- 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)
点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...
- 斜率优化DP 与数形结合思想
前言 最近才入了DP优化的大坑-- 发现斜率优化DP还是很有用的 下面会结合一道例题,同时讲解斜率优化DP 正文 先看一下例题:HDU3507 题目大意:有一串数列,要把它分割成若干段 每一段的代价是 ...
- NOI2007 货币兑换 - CDQ分治斜率优化dp
斜率优化dp维护一个凸壳.如果\(x, y\)坐标都递增,可以用单调队列,如果只有\(x\)递增,可以在凸壳上二分斜率,如果\(x, y\)都不递增,则需要在凸包中插入,可以用平衡树或cdq分治维护. ...
- CF-311B Cats Transport(斜率优化DP)
题目链接 题目描述 小S是农场主,他养了 \(M\)只猫,雇了 \(P\) 位饲养员. 农场中有一条笔直的路,路边有 \(N\) 座山,从 \(1\) 到 \(N\)编号. 第 \(i\) 座山与第 ...
- APIO2010 特别行动队 斜率优化DP算法笔记
做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$ 可以变形为 $f[i]=max((a*sum[j ...
最新文章
- 《面向对象程序设计》c++第五次作业___calculator plus plus
- SharePoint 沙盒解决方案 VS 场解决方案
- 开启nginx状态监控
- 转 ajax.dll 与 ajaxpro.dll的用法
- 百行代码制作自己的夸夸语料库,打造聊天机器人
- chromedriver不在路径的解决办法
- python之deque
- 几个 h5页面效果和 自动 app 生成网站 微页
- css3 颜色 文本
- 双目测距相似三角形原理
- BootStrap 点击展示气泡框
- python爬虫爬取知乎图片,轻松解决头像荒
- php控制打印机打印设置,专为控制打印设计的CSS样式
- 如何将深度学习与你正在做的事情相结合?
- python,人工智能,水果识别
- 如何优雅的写C++代码 Obotcha介绍(字符串转uint8_t)
- 企微获客助手是什么?企微即将上线“获客助手”功能
- Adobe Acrobat XI经验总结(更于2022.5.11)
- linux c 删除文件,linux c remove 删除文件或目录函数
- Casual inference 综述框架