HDU3507 Print Article —— 斜率优化DP
题目链接: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
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.
5
9
5
7
5
题意:
给出一段字符串,每个位置上的字符都有其相应的价值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的更多相关文章
- HDU3507 Print Article(斜率优化dp)
前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...
- hdu3507 Print Article[斜率优化dp入门题]
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- [hdu3507 Print Article]斜率优化dp入门
题意:需要打印n个正整数,1个数要么单独打印要么和前面一个数一起打印,1次打印1组数的代价为这组数的和的平方加上常数M.求最小代价. 思路:如果令dp[i]为打印前i个数的最小代价,那么有 dp[i] ...
- HDU3507 Print Article (斜率优化DP基础复习)
pid=3507">传送门 大意:打印一篇文章,连续打印一堆字的花费是这一堆的和的平方加上一个常数M. 首先我们写出状态转移方程 :f[i]=f[j]+(sum[i]−sum[j])2 ...
- hdu 3507 Print Article(斜率优化DP)
题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...
- Print Article /// 斜率优化DP oj26302
题目大意: 经典题 数学分析 G(a,b)<sum[i]时 a优于b G(a,b)<G(b,c)<sum[i]时 b必不为最优 #include <bits/stdc++.h& ...
- 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 ...
- hdu3507Print Article(斜率优化dp)
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU-3507Print Article 斜率优化DP
学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...
随机推荐
- VMware虚拟机 NAT模式 配置静态ip
前言:Ubuntu 16.04 VMware虚拟机 NAT模式 配置静态ip,这个问题困扰我好长时间,桥接的静态ip我会了,然而用NAT 的方式配置集群会更好.(NAT 方式客户机之间的通讯不经过路由 ...
- 用 Jackson 来处理 JSON
Jackson 是一个 Java 用来处理 JSON 格式数据的类库,性能非常好. 首先创建一个User对象类 (User.java) package com.sivalabs.json; impor ...
- 「CodePlus 2018 4 月赛」最短路
$n \leq 100000$,$m \leq 500000$的有向图,两点之间还可以以$a \ \ xor \ \ b$的代价从$a$到$b$,问$s$到$t$的最短路. 被自己蠢哭QAQ 首先两个 ...
- Java面试题集(一)
作为一名java开发软件工程,一定要记住,基础非常重要,往往就是一些基础,很简单,但是你就是不知道实现原理,为什么使用,有没有自己去发现,对比,差异从而总结,有些东西看似简单,但是不一定你描述清楚,直 ...
- 清除svn检出导致的所有文件的问号
问题:将svn项目检出到桌面后,桌面的图标都有问号了,怎么消除这一大堆问号? 解决方案:(1)新建一个a.txt文件,把这行代码复制进去for /r . %%a in (.) do @if exist ...
- Mysql Binlog日志文件介绍
一.Binlog简介 官方文档参考 https://dev.mysql.com/doc/refman/5.5/en/binary-log.html Binlog(Binary Log) 指数据库的表创 ...
- htmlcxx取指定字段实例
#include <string> #include <iostream> #include <sstream> #include <htmlcxx/html ...
- 《深入理解mybatis原理》 Mybatis初始化机制详解
对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章将通过以下几点详细介绍MyBatis的初始化过程. 1.MyBatis的初始化做了什么 2. MyBatis基于XML配置 ...
- websocket笔记
本文为原创,转载请注明出处: cnzt 文章:cnzt-p http://www.cnblogs.com/zt-blog/p/6742746.html websocket -- 双向通信网 ...
- spring mvc拦截器原理分析
我的springMVC+mybatis中的interceptor使用@autowired注入DAO失败,导致报空指针错误,这个是为什么呢? :空指针说明没有注入进来,你可以检查一下你的这个拦截器int ...