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的正方形)

当然,如果这个点的左上,左和上都能作为右下角构建2
2的正方形,那么以这个点为右下角就能构建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入门到入土】的更多相关文章

  1. poj 3254 状压dp入门题

    1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...

  2. xbz分组题B 吉利数字 数位dp入门

    B吉利数字时限:1s [题目描述]算卦大湿biboyouyun最近得出一个神奇的结论,如果一个数字,它的各个数位相加能够被10整除,则称它为吉利数.现在叫你计算某个区间内有多少个吉利数字. [输入]第 ...

  3. 【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] = ...

  4. 数位dp入门 hdu2089 不要62

    数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...

  5. POJ 2342 树形DP入门题

    有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...

  6. hdu3555 Bomb 数位DP入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 简单的数位DP入门题目 思路和hdu2089基本一样 直接贴代码了,代码里有详细的注释 代码: ...

  7. 【专章】dp入门

    动态规划(简称dp),可以说是各种程序设计中遇到的第一个坎吧,这篇博文是我对dp的一点点理解,希望可以帮助更多人dp入门. ***实践是检验真理的唯一标准,看再多文章不如自己动手做几道!!!*** 先 ...

  8. HDU 2084 数塔(简单DP入门)

    数塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  9. 树形dp 入门

    今天学了树形dp,发现树形dp就是入门难一些,于是好心的我便立志要发一篇树形dp入门的博客了. 树形dp的概念什么的,相信大家都已经明白,这里就不再多说.直接上例题. 一.常规树形DP P1352 没 ...

随机推荐

  1. 函数的学习3——传递任意数量的实参&将函数存储在模块——参考Python编程从入门到实践

    传递任意数量的实参 形参前加一个 * ,Python会创建一个已形参为名的空元组,将所有收到的值都放到这个元组中: def make_pizza(*toppings): print("\nM ...

  2. quartz2.3.0(七)调度器中断任务执行,手动处理任务中断事件

    job任务类 package org.quartz.examples.example7; import java.util.Date; import org.slf4j.Logger; import ...

  3. [LOJ#3119][Luogu5405][CTS2019]氪金手游(DP+容斥)

    先考虑外向树的做法,显然一个点在其子树内第一个出现的概率等于它的权值除以它子树的权值和.于是f[i][j]表示i的子树的权值和为j时,i子树内所有数的相互顺序都满足条件的概率,转移直接做一个背包卷积即 ...

  4. go 基本IO接口

    package main import ( "fmt" "io" "strings" ) func ReadFrom(reader io.R ...

  5. Spring Boot异步发送邮件和请求拦截器配置

    用户登录流程图: 在spring拦截器中进行鉴权操作: 控制器的拦截: import com.mooc.house.common.model.User; import org.springframew ...

  6. Java 二叉搜索树 实现和学习

    /** * <html> * <body> * <P> Copyright 1994 JsonInternational</p> * <p> ...

  7. 修改CentOS默认yum源为国内镜像

    参考文档 https://blog.csdn.net/inslow/article/details/54177191 国内主要开源的开源镜像站点应该是网易和阿里云了. 修改为163yum源-mirro ...

  8. 原生JS获取HTML DOM元素的8种方法

    JS获取DOM元素的方法(8种) 通过ID获取(getElementById) 通过name属性(getElementsByName) 通过标签名(getElementsByTagName) 通过类名 ...

  9. 巧用CSS3之background渐变

    常见斑马loading 上图是我们常见的loading进度条,以前都是用一张背景图片平铺的.其实如果抛去兼容性因素,我们可以用零图片纯样式来实现. 一,首先,我们先为容器定义一个纯蓝色背景: box{ ...

  10. Jenkins 构建方式有几种

    jenkins三种部署方式: 一.jenkins触发式构建:用于开发环境部署,开发人员push代码或者合并代码到gitlab项目的master分支,jenkins就部署代码到对应服务器. 二.jenk ...