首先要感谢叉姐的指导Orz

这一类问题的DP方程都有如下形式

dp[i] = w(i) + max/min(a(i)*b(j) + c(j)) ( 0 <= j < i )

其中,b, c均为j的单调函数。通常情况下a(i)也是单调的,a(i)不单调时就只能二分查找了。

这里讲一下当c(j)单调递增,b(j)单调递减,原方程求min的情况

对于同一j,b(j),c(j)为常数,而a(i)为变量,令y = b(j) * x + c(j),则y为线性函数

我们把( 0 <= j < i )的直线均表示在平面上,则如下图所示。

显然,对于不同的dp[i],我们要求的是在对应x = a(i)下所有直线的最小值

看图我们可以发现,就是这些直线的下半平面交的边缘组成的分段函数,就是我们要求的函数

那么怎么维护这个半平面呢

首先b(j)最小的直线,必然会在足够大处,取得所有直线的最小值

我们在维护的过程中,总是在原半平面交的基础上,加上一个c(j)最大,b(j)最小的直线

这个时候,这条直线必然会加入半平面交当中。

同时,有可能会导致有些直线被遮蔽而退出集合。

我们可以发现,如果j=k的直线没有被遮蔽,那么j=[0,k)的直线也显然不会被遮蔽。

所以我们只需要从原来的半平面交最大的j开始不停的向内找,直到找到第一个没被遮蔽的直线就可以了。

那么直线什么时候会被遮蔽呢?

直线只剩两条的时候,显然不会有直线被遮蔽→ →

观察图中的直线1,2,3以及直线2,3,4。

2没有被遮蔽,是因为2和1的交点在2和3的交点左边。

而3被遮蔽,是因为3和2的交点在3和4的交点的右边。

所以只需要求交点然后比较大小就可以了。(两直线求交,初中知识,相信大家都会,请自行计算)

这里需要注意的是,求交点需要用到除法。但是除法容易出现精度问题,我们要把除法在比较的时候移到另一侧变成乘法,这个时候记得注意正负变号。

这个维护过程,考虑每个直线最多进出队列一次,复杂度总计O(n)

维护好半平面集合,后,求x = a(i)时的值,只需要二分判断落在哪个直线的交点区域内就好了。

特殊的,如果a(i)也单调,则可以像单调队里那样从头部一一剔除的方法,这里不多做介绍。

理解上述部分后,假如b(j),c(j)都不单调,问题则转变为动态半平面交。

另外,其实有没有发现写起来和凸包的理解非常像?叉姐告诉我们,其实根据平面的点与直线的对偶,凸包和半平面交问题是完全等价的。

附HDU 3669代码

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=; pair<int,int> a[N],s[N];
int n,m; int l,r;
pair<int,ll> q[N]; int x,y;
ll dp[][N]; inline void push(int k,ll b){
while(l<r && (q[r].second-q[r-].second)*(q[r].first-k)>=(b-q[r].second)*(q[r-].first-q[r].first)) r--;
q[++r]=make_pair(k,b);
} inline void pop(ll x){
while(l<r && (q[l].first - q[l+].first)*x >= q[l+].second - q[l].second) l++;
} int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=;i<n;i++)scanf("%d%d",&a[i].first,&a[i].second);
sort(a,a+n);
int cnt=,mxb=a[n-].second;
s[]=a[n-];
for(int i=n-;i>=;i--)if(a[i].second>mxb){
mxb = a[i].second;
s[cnt++]=a[i];
}
n=cnt;
ll mxa=s[].first;
for(int i=;i<n;i++) dp[][i]=mxa*s[i].second;
ll ans=dp[][n-];
x=;
y=;
if(m>n) m=n;
for(int k=;k<m;k++){
l=;r=-;
push(s[k].first,dp[x][k-]);
for(int i=k;i<n;i++){
pop(s[i].second);
dp[y][i]=q[l].second+(ll)q[l].first*s[i].second;
push(s[i+].first,dp[x][i]);
}
x^=;
y^=;
if(dp[x][n-]<ans) ans=dp[x][n-];
else break;
}
printf("%I64d\n",ans);
}
return ;
}

动态规划DP的斜率优化 个人浅解 附HDU 3669 Cross the Wall的更多相关文章

  1. hdu 3669 Cross the Wall(斜率优化DP)

    题目连接:hdu 3669 Cross the Wall 题意: 现在有一面无限大的墙,现在有n个人,每个人都能看成一个矩形,宽是w,高是h,现在这n个人要通过这面墙,现在只能让你挖k个洞,每个洞不能 ...

  2. HDU 3669 [Cross the Wall] DP斜率优化

    问题分析 首先,如果一个人的\(w\)和\(h\)均小于另一个人,那么这个人显然可以被省略.如果我们将剩下的人按\(w[i]\)递增排序,那么\(h[i]\)就是递减. 之后我们考虑DP. 我们设\( ...

  3. HDU 3669 Cross the Wall(斜率DP+预处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3669 题目大意:有n(n<=50000)个矩形,每个矩形都有高和宽,你可以在墙上最多挖k个洞使得 ...

  4. dp的斜率优化

    对于刷题量我觉得肯定是刷的越多越好(当然这是对时间有很多的人来说. 但是在我看来我的确适合刷题较多的那一类人,应为我对知识的应用能力并不强.这两天学习的内容是dp的斜率优化.当然我是不太会的. 这个博 ...

  5. 【DP】斜率优化

    斜率优化 入门题:PKU3709 很多人貌似都是做这道题来K斜率优化的,所以看了资料以后还是开始入手吧. 然而还是得跪求大神的程序啊 ORZ ORZ…… 其实理解斜率优化就是会列斜率不等式,还要理解剔 ...

  6. bzoj 1010 [HNOI2008]玩具装箱toy(DP的斜率优化)

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7874  Solved: 3047[Submit][St ...

  7. 洛谷P3195 [HNOI2008] 玩具装箱 [DP,斜率优化,单调队列优化]

    题目传送门 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N ...

  8. 【HDOJ5956】The Elder(树形DP,斜率优化)

    题意:有一棵n个点的有根树,每条边上有一个边权.给定P,从i跳到它的祖先j的费用是距离的平方+P,问所有点中到根节点1的总花费最大值 n<=1e5,p<=1e6,w<=1e2 思路: ...

  9. CF1179D Fedor Runs for President [DP,斜率优化]

    Codeforces 思路 考虑把连的那两个点中间的链提出来,那么就会变成一条链,链上的每个点挂着一棵子树的形式. 设那些子树的大小为\(S_1,S2,\cdots\),那么新加的简单路径个数就是 \ ...

随机推荐

  1. python基础数据类型之字符串操作

    1.字符串切片ps:字符串是不可变的对象, 所以任何操作对原字符 是不会有任何影响的 s1 = "python最简洁" print(s1[0]) print(s1[1]) prin ...

  2. jquery动态改变元素内容

    ● text() - 设置或返回所选元素的文本内容 ● html() - 设置或返回所选元素的内容(包括 HTML 标记) ● val() - 设置或返回表单字段的值(只针对表单或者输入框)

  3. gdb-pada调试实例

    先编写个简单的hello的程序 hello.c (ps:有没有头文件行不行,试试不就知道了) int main(){ printf("hello!\n"); int m,n; in ...

  4. 记一次微信小程序在安卓的白屏问题

    在做小程序的时候,做到了一个限时商品售卖,用到了倒计时,因为这个原因导致了安卓手机上使用小程序时,将小程序放入后台运行一段时间后,再次进入小程序后出现了页面白屏或者点击事件失效的情况,这里记录下 1. ...

  5. iOS常用控件-UIScrollView

    一. 常见属性 @property (nonatomic) CGPoint contentOffset;                      //记录UIScrollView滚动的位置 @pro ...

  6. ln -s 软链接产生Too many levels of symbolic links错误

    不能使用相对路径, ln -s ./cmake /usr/bin/ 而是要 ln -s /usr/local/bin/cmake /usr/bin/

  7. Echarts 背景渐变柱状图

    var dom = document.getElementById("container"); var myChart1 = echarts.init(dom); var app ...

  8. 9,Flask 中的蓝图(BluePrint)

    蓝图,听起来就是一个很宏伟的东西,在Flask中的蓝图 blueprint 也是非常宏伟的,它的作用就是将 功能 与 主服务 分开. 比如说,你有一个客户管理系统,最开始的时候,只有一个查看客户列表的 ...

  9. WPF图片预览之移动、旋转、缩放

    原文:WPF图片预览之移动.旋转.缩放 RT,这个功能比较常见,但凡涉及到图片预览的都跑不了,在说自己的实现方式前,介绍一个好用的控件:Extended.Toolkit中的Zoombox,感兴趣的同学 ...

  10. Invalid bound statement (not found): com.up.sell.mapper.system.H5operationMapper.

    springboot + mybatis项目,出现这样的错误原因就是mapper类的名字和xml的id不对应或者是忘记写了,仔细检查一下吧