【DP入门到入土】
DP例题较多,可以根据自己需求食用~
update:下翻有状压DP入门讲解,也只有讲解了(逃~
DP的实质,就是状态的枚举。
一般用DP解决的问题,都是求计数或最优问题,所以这类问题,我们也可以用搜索来解决。
但是,之所以出现DP,就是因为在有些情况下,搜索不能以较高的效率求解,题目也不需要记录过程,而DP是直接记录答案,不记录过程,效率较高,所以深受广大OIer的唾弃喜爱。
所以写DP的难点就在如何表示每一个状态并利用它快速推出我们想得到的答案。
让我们通过一些毒瘤经典例题来练习DP吧awa
引入
1.走楼梯
题目传送门
明显这道题就是一个DP,还是很入门那种
但既然是引入,还是有必要讲讲的。
既然这位老哥一次可以跨1或2步,那么每一阶的方案数就是前两阶的方案数之和,即dp[i]=dp[i-1]+dp[i-2]
。
当然,没有初始值递推是跑不起来的,这道题目的初始值就是dp[0]=1,dp[1]=1
站着不动1种,走一步1种。
然后从2~n推一遍,输出dp[n]
就可以了。
code
2.数塔问题
题目传送门
作为引入的第二道题目依然水到爆
很明显的,这道题目需要一点贪心的思想,每次选择左上和上方较大的一个,由较大那个数的dp值加上这个点本身输入的那个值,最后遍历最后一行的dp值取max即可。
code
例题
1.传球问题
题目传送门
这道题初一看好像真的想不出该怎么做,但是在同机房大佬的提醒下 应该用DP!
我们用dp[m][n]
表示第m次传递后第n个小朋友的传娃娃方法数,很明显,我们需要求的即是dp[m][1]
的值。找到边界值:dp[0][1]=1;
然后可以发现,一个状态转移方程是无法解决这个比较复杂的dp的,需要添加if语句达到效果。
于是我开始讨论有哪些可能。因为这道题是直接用的dp,并没有构建环,所以这是需要特殊考虑的。然后,我们发现,第i次传递后的点k的方案数,只能由第i-1次传递后的点k的左右两人的方案数之和来得到!
但是如上所述,当这个点是1或n时需要特判,所以情况分为三种:
①这个点是1时:dp[i][j]=dp[i-1][j+1]+dp[i-1][n];
②这个点是n时:dp[i][j]=dp[i-1][j-1]+dp[i-1][1];
③这个点是普通点(非1非n时):dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1];
然后双重循环,外层1…->m,内层1…->n,完事输出dp[m][1]
即可。
code
2.最小乘车费用
题目传送门
dp题目,本质是完全背包。
完全背包不懂的可以去百度一下。
状态转移方程式dp[j]=min(dp[j],dp[j-i]+a[i]);
其实就是一个选不选选多少的问题,只不过循环的顺序需要注意一下。
另外,除了dp[0]
以外,其他的dp值都要赋为极大值(没选之前都是无效的所以要极大值)
code
3.最大子段和
题目传送门
这道题目暴力是很容易做出来的...但明显效率太低,重点讲一下从暴力到dp的方法。
1)暴力枚举左右端点,循环求值取max。
这种方法真的暴力。。时间复杂度达到了\(O(n^3)\),在这道题目\(n\leq200000\)的数据范围下会TLE得很惨%%%
2)前缀和枚举优化
比方法1少了循环求值的过程,p[i]
表示从1-n的值的和,求区间值直接相减就可以了。
时间复杂度\(O(n^2)\),不出意外的依然会T
3)贪心/DP
这种方法是这道题目的正解,时间复杂度只有\(O(n)\)。
大致思路:设置一个cnt和一个maxx,maxx的初值为第一个输入的数,然后后面每次输入贪心,判断选这个数加入是否要更优,然后缩进左端点,更新cnt,更新ans(取max)
code
4.*最长公共子序列
跟dp没啥关系但是值得了解。
前置知识:求最长上升子序列
p.s. 子序列不是子段,子序列只要求在原串中按顺序出现,不需要连续出现
题目传送门
思路:
知道怎么求最长上升子序列就很简单。因为两个串都是1-n的一个排列,所以元素是相同的。
我们把第一个串的n个数分别对应1-n,让第一个串变成1-n的一个顺序排列(第i个数变成i)
然后按照这个规律,把第2个串也变一下(比如1串中3变成了5,那么2串中的3也要变成5)
然后在2串中找最长上升子序列就可以了,要用二分不然会炸。
原理很好理解,1串经过变化已经变成一个上升串了,又因为两个串中的元素都是相同的,所以找出2串中的最长上升子序列就可以了。
code
5.最大正方形
题目传送门
这道题是在一个01矩阵中找出最大的由1组成的最大的正方形的边长。
输入的原图我们用a数组存起来,当然是二维的。
然后我们用f[i][j]表示以点(i,j)为右下角的正方形的最大边长。
拿样例来说,f[2][2]的值就是1,f[3][3]的值就是2(可以画一个22的正方形)
然后每次更新的时候判断,首先这个点的值得是1,因为表示的是右下角,所以就看左上,左和上的f[i][j]值,取min+1作为自己的f值。
为什么要这样做呢?很明显,如果自己的左上,左和上有任意一个是0,那么这个点的f值一定是1(取min+1)而如果它们都是1,那么这个点的f值就是2(能放出边长为2的正方形)
当然,如果这个点的左上,左和上都能作为右下角构建22的正方形,那么以这个点为右下角就能构建3*3的正方形(可以画图理解一下)
code
6.最大正方形II
题目传送门
和上一道题目类似,但是拓展时判断的标准从它的值是否是1变成了它是否和左上相同并且和左、上不同(因为要岔开)
代码中要修改的也只有这一处。。
code
*状态压缩DP
动态规划的状态有时候比较恶心,不容易表示出来,需要用一些编码技术,把状态压缩的用简单的方式表示出来。
典型方式:当需要表示一个集合有哪些元素时,往往利用2进制用一个整数表示。比如01背包问题,选表示成1,不选表示成0。
就拿'110101'来说,从低位来看,表示:1选,2不选,3选,4不选,5选,6选。n个物品选取方案的表示信息一定在\([0,2^n-1]\)之间。
动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了。难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划。
先介绍一下常用的位运算:
- 按位与:
&
,把操作的两个数的二进制按位与,两个数的第i位都是1,得到的数的第i位才是1. - 按位或:
|
,把操作的两个数的二进制按位或,任意一个数的第i位是1,得到的数的第i位才是1. - 按位异或:
^
(虽然它平时表示计算符号但是这里它是一个位运算符号):把操作的两个数的二进制按位异或,两个数的第i位不同,得到的数的第i位才是1. - 取反:
~
,只有一个操作数,把这个数的二进制的每一位都取反(0变1,1变0) - 左移:
<<
,把操作数的二进制数左移N位,低位用0补上 - 右移:
>>
,把操作数的二进制数右移N位,被移出的舍去
有什么用呢?
它快啊!它的计算速度的确比普通的四则运算要快一些,并且也有一些奇怪神奇的作用。
比如树状数组中会用到的,利用了负数补码的性质,找出x最低位的1的位置,方便树状数组的使用:
int lowbit(int x)
{
return x&(-x);
}
但是需要注意的,位运算的计算优先度较低,请配合括号食用awa
例题后面刷了再更新吧...
【DP入门到入土】的更多相关文章
- poj 3254 状压dp入门题
1.poj 3254 Corn Fields 状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...
- xbz分组题B 吉利数字 数位dp入门
B吉利数字时限:1s [题目描述]算卦大湿biboyouyun最近得出一个神奇的结论,如果一个数字,它的各个数位相加能够被10整除,则称它为吉利数.现在叫你计算某个区间内有多少个吉利数字. [输入]第 ...
- 【dp入门题】【跟着14练dp吧...囧】
A HDU_2048 数塔 dp入门题——数塔问题:求路径的最大和: 状态方程: dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+a[i][j];dp[n][j] = ...
- 数位dp入门 hdu2089 不要62
数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...
- POJ 2342 树形DP入门题
有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...
- hdu3555 Bomb 数位DP入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 简单的数位DP入门题目 思路和hdu2089基本一样 直接贴代码了,代码里有详细的注释 代码: ...
- 【专章】dp入门
动态规划(简称dp),可以说是各种程序设计中遇到的第一个坎吧,这篇博文是我对dp的一点点理解,希望可以帮助更多人dp入门. ***实践是检验真理的唯一标准,看再多文章不如自己动手做几道!!!*** 先 ...
- HDU 2084 数塔(简单DP入门)
数塔 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...
- 树形dp 入门
今天学了树形dp,发现树形dp就是入门难一些,于是好心的我便立志要发一篇树形dp入门的博客了. 树形dp的概念什么的,相信大家都已经明白,这里就不再多说.直接上例题. 一.常规树形DP P1352 没 ...
随机推荐
- python_scratch教程:绘制荧光圈教程
在演唱会中,出现最多的就是荧光棒,很多粉丝也都会举着荧光棒为自己的爱豆加油,当然也会有一些人用的荧光圈,为此南京小码王scratch培训机构,就想到了和小朋友一起绘制荧光圈,现在我们就一起来看看吧! ...
- Prism
网址:https://prismjs.com 使用教程:https://www.cnblogs.com/zhibu/p/6272338.html 使用教程:https://www.zlinet.com ...
- CCS中的linked resource
一.关于CCS中的linked resource linkded resources 是eclipse中的一个功能,可以将存放在项目所在位置以外某个路径的文件或者文件夹链接至工程项目中.这个功能最大的 ...
- vue页面params传值的必须传name
a.vue向b.vue传值 a.vue this.$router.push({ path: '/payType', query: { putUpList: this.putUpList, name:' ...
- LOJ6300 博弈论与概率统计 组合、莫队
传送门 如果在\(0\)以下之后仍然会减分,那么最后的结果一定是\(N-M\). 注意到如果在Alice分数为\(0\)时继续输,那么就相当于减少了一次输的次数.也就是说如果说在总的博弈过程中,Ali ...
- 单实例dg软件从10.2.0.4版本安装至10.2.0.5.12
DG环境搭建需求,因此安装与主库相同的软件版本 1.主库软件版本10.2.0.5.12 2dg环境提供的是全新的10.2.0.4.0 3.安装步骤,安装10.2.0.5 静默安装 psu安装10.2. ...
- Python之TensorFlow的基本介绍-1
一.TensorFlow™是一个基于数据流编程(dataflow programming)的符号数学系统,被广泛应用于各类机器学习(machine learning)算法的编程实现,其前身是谷歌的神经 ...
- .Net Core-类库中创建CodeFirst
本文仅用来学习记录. 搭建项目架构的时候,需要在类库中进行CodeFirst数据迁移 1.在项目的解决方案中,添加类库ERPFrame.Model 2.在类库项目中 添加实体模型和数据上下文 其中 ...
- iOS 播放系统自带铃声
播放声音代码例子 https://github.com/baitongtong/git-.git 给一个国外网址,苹果系统铃声以及自定义铃声免登陆免费下载:http://www.zedge.net/r ...
- TR-银行通信相关文档
DMEE配置指南: https://wenku.baidu.com/view/06790649767f5acfa1c7cd73.html F110 DMEE配置: https://wenku.baid ...