1D/1D动态规划学习总结
前言:
自从发现1D/1D动态规划这个新的技能块后,每次看到这类题目都能口嗨成功,然后队友催我赶紧学。再者发现有好多优化方法,所以慢慢学,每天学一点,加上还要做一些奇奇怪怪的题目保持状态,也就差不多了。
第0天(1D/1D动态规划)
什么是1D/1D动态规划?
1D/1D动态规划是指形如dpi=max{dpj+w(i,j)}dp_{i}=max\{ dp_{j}+w(i,j)\}dpi=max{dpj+w(i,j)}的动态规划,当然maxmaxmax也可以换成minminmin。
据说长这样的dpdpdp一般都可以优化到o(nlogn)o(nlogn)o(nlogn)。
优化的思路就是在jjj的范围中,快速找到一个最优的转移点。
学习思路大概就是学习这个转移方程的不同类型,然后对于每种类型学习它的优化方法。
学习链接(多去走走,这样笔者偷完知识就不会愧疚了,博客里会加入自己的东西(也许))
第0.5天(前缀和优化)
有个前缀和优化,这个笔者默认会了,就不学了。不会的话请读者自行学习。
第1天(单调队列优化)
啊~新的力量!
今天是单调队列优化dp,当然,就当大家都会单调队列了。
实话说,学完感觉原来的dpdpdp式也有点不恰当,我们把dpjdp_{j}dpj也看作是w(i,j)w(i,j)w(i,j)中jjj的一部分运算,那式子其实就是dpi=max{w(i,j)}dp_{i}=max\{ w(i,j)\}dpi=max{w(i,j)}。
好了,进入今天的正题。
按照我们的学习思路,我们应该对于此类优化,有一个归纳的转移式子,那就有了。
转移方程
dpi=max{w(j)}dp_{i}=max\{ w(j)\}dpi=max{w(j)}
说明
这个方程的意思就是dpdpdp的转移只和jjj有关。然后这个jjj呢,一般是一个区间范围,并且随着iii的变大,jjj的范围区间是整体右移的。这样可以保证它能在转移过程中,用单调队列找到最优点。
思路:
说明中提到jjj的范围区间整体右移,我们设转移dpi−1dp_{i-1}dpi−1时jjj的范围区间是[li−1,ri−1][l_{i-1},r_{i-1}][li−1,ri−1],转移dpidp_{i}dpi时jjj的范围区间是[li,ri][l_{i},r_{i}][li,ri]。那么我们rrr变大的时候,就把新的元素加入到单调队列右边(如果要加的话,在这之前还要把右边一些不要的元素拿走),然后答案在队列左边找到范围内的。当然,这都是单调队列的东西,就不细讲了。
实战例题
PTA-Little Bird
题意
nnn棵树,每棵树有一个高度did_{i}di,小HHH在第111棵树上,要跳到第nnn棵树上。在第iii棵树上时,可以跳到第i,i+1,…,i+ki,i+1,…,i+ki,i+1,…,i+k棵树上。每跳一次,如果高度不小于原来的高度,疲劳值就会加111。现在问小HHH从第111棵树上跳到第nnn棵树上,最少的疲劳值是多少。
(1≤n≤k≤106)(1\leq n\leq k\leq 10^{6})(1≤n≤k≤106)
思路
我们设状态dpidp_{i}dpi表示跳到第iii棵树上需要花费的最少疲劳值。
那么有转移方程dpi=min{dpj+[di>=dj]}dp_{i}=min\{dp_{j}+[d_{i}>=d_{j}]\}dpi=min{dpj+[di>=dj]},其中j∈[i−k,i−1]j\in [i-k,i-1]j∈[i−k,i−1]。
我们要学习这个思路。
首先我们观察j∈[i−k,i−1]j\in [i-k,i-1]j∈[i−k,i−1],我们发现区间随着iii变大整体右移,成立。
然后dpj+[di>dj]dp_{j}+[d_{i}>d_{j}]dpj+[di>dj],它是一个关于iii和jjj的式子,呃好像不成立。
这时候只能发挥我们的聪明才智了,咳咳。
我们先发现dpidp_{i}dpi单调不下降,且每次增加都是加111。所以对于两个dpjdp_{j}dpj的值,我们肯定直接取小的那个,因为小的那个+1+1+1也不会超过大的。然后对于两个相同的dpjdp_{j}dpj,我们一定优先取djd_{j}dj大的那个,也就是要在范围内找使得(−dpj,dj)(-dp_{j},d_{j})(−dpj,dj)最大的jjj。这样就可以用单调队列优化了。
刚才演示翻车了,我决定用dpi=w(i,j),whereg(j)ismaxforjinrangedp_{i}=w(i,j),where\;g(j)\;is\;max\;for\;j\;in\;rangedpi=w(i,j),whereg(j)ismaxforjinrange来作为新式子。
这样也许就可以泛化模型了。
代码
题目有点卡,开o2优化就过了。
写完下班。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;int q[1000005],fr,bk;
int d[1000005];
int dp[1000005];
int w(int i,int j)
{return dp[j]+(d[i]>=d[j]);
}
P g(int j)
{return P(-dp[j],d[j]);
}
int main()
{int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&d[i]);int m;scanf("%d",&m);while(m--){fr=bk=0;int k;scanf("%d",&k);dp[1]=0;q[bk++]=1;for(int i=2;i<=n;i++){while(q[fr]<i-k)fr++;dp[i]=w(i,q[fr]);while(!(fr==bk)&&g(q[bk-1])<=g(i))bk--;q[bk++]=i;}printf("%d\n",dp[n]);}return 0;
}
第二天(分治优化)
(待续。。)
(upd:更新了标题后面不应该加冒号的bug)
昨天是关于jjj独立的转移,依据jjj的单调性用单调队列优化。
那么今天这个是不关于jjj独立,即和iii和jjj都有关的,刚学了一种分治优化,当然你得先会分治。
转移方程
dpi=max(w(i,j)),j∈[1,i−1]dp_{i}=max(w(i,j)),j \in [1,i-1]dpi=max(w(i,j)),j∈[1,i−1]
又或者说dpi=w(i,j),whereg(i,j)ismaxforjinrangedp_{i}=w(i,j),where\;g(i,j)\;is\;max\;for\;j\;in\;rangedpi=w(i,j),whereg(i,j)ismaxforjinrange
并且还需要它的转移,随着iii满足某种决策单调性。
说明
总之,我们需要找的最优转移点和i,ji,ji,j都有关。
然后,转移要随着iii满足决策单调性。举个例子,大致意思是,当iii 慢慢变大,最优决策点jjj也会慢慢变大。但这不意味着jjj大更优,有些jjj压根不会被作为最优决策点,只是哪些对每个iii作为最优决策点的jjj们是随着iii变大而变大的(不下降)。
思路
分治的大致做法是,我们先找中间的dpmiddp_{mid}dpmid的转移点qmidqmidqmid。然后根据决策单调性,当i<midi<midi<mid时,转移点j∈[1,qmid]j\in[1,qmid]j∈[1,qmid];当i>midi>midi>mid时,转移点j∈[qmid,n]j\in[qmid,n]j∈[qmid,n]且j<ij<ij<i。
然后每次这样取中点求最优转移点,把区间割成两个一半。递归深度是logloglog级的,那我们找转移点就暴力遍历可能存在最优转移点的决策区间。总体复杂度o(nlogn)o(nlogn)o(nlogn)。
实战例题
Lightning Conductor
题意
给定一个长度为nnn的序列{an}\{a_{n}\}{an},对于每个 i∈[1,n]i\in [1,n]i∈[1,n],求出一个最小的非负整数ppp,使得 ∀j∈[1,n]\forall j\in[1,n]∀j∈[1,n],都有 aj≤ai+p−∣i−j∣a_j\le a_i+p-\sqrt{|i-j|}aj≤ai+p−∣i−j∣
1≤n≤5×105,0≤ai≤1091\leq n\leq 5\times 10^{5},0\leq a_{i}\leq 10^{9}1≤n≤5×105,0≤ai≤109
思路
我们令dpidp_{i}dpi表示第iii个答案。
首先,把绝对值处理掉,我们可以正向跑一遍dpdpdp,再逆向跑一遍,求个最大值。
那么正向的转移方程就是dpi=max{aj−ai+i−j},j∈[1,i−1]dp_{i}=max\{a_{j}-a_{i}+\sqrt{i-j}\},j\in [1,i-1]dpi=max{aj−ai+i−j},j∈[1,i−1]。
关于iii常量先提出来,变成dpi=max{aj+i−j}−ai,j∈[1,i−1]dp_{i}=max\{a_{j}+\sqrt{i-j}\}-a_{i},j\in [1,i-1]dpi=max{aj+i−j}−ai,j∈[1,i−1]。
那么现在变成了,我们所说的模范转移式dpi=max{w(i,j)}dp_{i}=max\{w(i,j)\}dpi=max{w(i,j)},其中w(i,j)=ai+i−jw(i,j)=a_{i}+\sqrt{i-j}w(i,j)=ai+i−j。
然后,它要满足我们所说的决策单调性,即iii变大的时候,我们选取的最优决策点jjj也会慢慢变大。我们观察式子wj(i)=ai+i−jw_{j}(i)=a_{i}+\sqrt{i-j}wj(i)=ai+i−j是一个关于iii的函数,有i−1i-1i−1个这样的函数,我们要对于每个iii
选取一个最佳的函数wjw_{j}wj,使得函数值最高。
然后我们发现这些函数的增长速度都是慢慢变慢的,且wjw_{j}wj比wj+1w_{j+1}wj+1在iii相同时增长速度要慢。也就是一旦iii增长到某个时候wjw_{j}wj被一个wkw_{k}wk超过了,且k>jk>jk>j,那么wjw_{j}wj将永无翻身之日。
总的来说,就是满足当iii变大,最优决策点只会不断变大(或者换个题变小)。
满足我们前面所说的性质,然后就可以分治搞了。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;double a[500005];
ll dp1[500005],dp2[500005];
double w(int i,int j)
{return a[j]+sqrt(abs(i-j))-a[i];
}
void solve(int l,int r,int ql,int qr,ll *dp)
{if(l>r||ql>qr)return ;int mid=(l+r)/2;int qmid=ql;for(int i=ql;i<=qr&&i<mid;i++)if(w(mid,i)>w(mid,qmid))qmid=i;dp[mid]=ceil(w(mid,qmid));solve(l,mid-1,ql,qmid,dp);solve(mid+1,r,qmid,qr,dp);
}
int main()
{int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%lf",&a[i]);solve(1,n,1,n,dp1);reverse(a+1,a+n+1);solve(1,n,1,n,dp2);reverse(dp2+1,dp2+n+1);for(int i=1;i<=n;i++)printf("%lld\n",max(0ll,max(dp1[i],dp2[i])));return 0;
}
第N天
(待续。。)
拿金了,先断更了
1D/1D动态规划学习总结相关推荐
- [HNOI2008]玩具装箱(1D/1D动态规划)
[HNOI2008]玩具装箱 题目描述 P 教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中. P ...
- html z-dext优先级顺序,$ext{1D/1D}$ 动态规划的三种优化
神必博主的沙雕前言 参考文献: 概念明晰 所谓 (ext{1D/1D}) 动态规划, 指的是状态数和单状态决策数都是 (O(n)) 的动态规划方程, 暴力求解的时间复杂度为 (O(n^2)). 四边形 ...
- 自适应动态规划学习笔记(3)
@TOC 自适应动态规划学习笔记(3) 第三天(图全是偷的) 图1 ADP的三个部分 Model Network 书接上回,图(1)中所示的Model Network就是对于系统公式(1)xk+1= ...
- 动态规划学习记录:题型/思路汇总
#动态规划学习记录# 动态规划学习记录:题型/思路汇总 一维数组动态规划 1.爬楼梯 2.数硬币 3.最大子序和 4.区域和检索 - 数组不可变 5.整数拆分 6.打家劫舍 7.打家劫舍II 8.解码 ...
- 1D/1D动态规划的三种优化方法
1D/1D1D/1D1D/1D动态规划 形如dp[i]=min{dp[j]+w(j,i)}(Li≤j≤Ri)dp[i]=min\{dp[j]+w(j,i)\} (L_i\leq j\leq R_i)d ...
- 动态规划学习之三种方法解决斐波拉契数
斐波拉契数是一个很经典的问题,也会很多公司面试的考题,每个学习计算机的同学都会接触这个问题,尤其是在学习递归的时候,利用递归来解决斐波拉契数是很多教材采用的一个例子,所以很多同学一想到斐波拉契马上就会 ...
- 动态规划学习的一波记录
动态规划的概念 动态规划算法把原问题视作若干个重叠子问题的逐层递进,每个子问题的求解过程都构成了一个"阶段".在完成前一个阶段的计算后,动态规划才会执行下一个阶段的计算. 为了保证 ...
- 动态规划学习心得分享
最近在代码随想录(代码随想录)刷了一些有关动态规划的算法题,收获还蛮大的,下面是我的一些学习心得分享,不足之处敬请批评指正~ 首先来简单介绍一下什么是动态规划以及动规与贪心有何区别? 动态规划(Dyn ...
- 算法-动态规划学习(含经典例子分析)
文章目录 前言 一.动态规划是什么? 二.经典例子 爬楼梯问题 挖金矿问题 三.总结 前言 在leetcode刷题的过程中,碰到了许多动态规划相关的题目,故系统性的学习了动态规划算法.此文章总结了学习 ...
最新文章
- 各个数据库取前10行记录
- 其他算法-卡尔曼滤波器
- javascript: new Date(string)在IE中显示NaN的问题!
- Reporting Services 安装的备份和还原操作
- 解决cell循环利用造成的重复勾选
- CF1080F Katya and Segments Sets
- notempty注解属于哪个依赖_Spring框架 之@Valid注解的使用(嵌套类型的效验)
- local variable 'xxx' referenced before assignment
- Django模板层:模板继承 extends标签和block标签,csrf_token标签
- mysql数据库表无法显示_【MySQL8.0.18】IDEA 连接数据库无法显示数据表
- Linux分区和加密分区操作
- [Android] SharedPreferences(轻量级的存储方式)
- deepin显卡驱动管理器在哪_deepin显卡设置
- 2017吉比特校招一个编程笔试题
- python readcsv读取gbk编码文件_python读写csv文件
- 背景建模方法论文总结
- 基于深度学习的RGBD深度图补全算法文章鉴赏
- 奈学教育大数据架构分享下载
- Docker 从入门到入坑。
- 杰卡德相似系数(Jaccardsimilarity coefficient)
热门文章
- DNSPod十问Matt Overman:二维码真的代替域名了吗?
- 肥牛是不是牛肉,为什么?
- 将windows下文件编码格式转换成UTF-8 文件编码格式
- python为什么是蛇_【大蟒蛇】简谈Python的闭包【原创】
- php artisan migrate,laravel php artisan migrate错误
- java运行环境下载(我的世界Java运行环境)
- 中国成为北极理事会正式观察员国 将享合法权利
- 《MySQL必知必会》学习笔记——组合查询、全文本搜索
- 计算机设备的快捷命令,快速打开设备管理器的快捷键教程
- 《花千骨》为何被批“脑残”还能创造收视神话?