动态规划(DP)基础
DP基础
- 简单dp
- 背包问题
- 记忆化搜索
简单dp
数字三角形
给一个数字构成的三角形,求从顶端走到底部的一条路径,使得路径上的和最大(或者最小)。
1 2 3 6 5 4 Example_1 7 3 8 8 1 0 5 2 6 100000 Example_2
根据Example_2可以知道贪心显然是不正确的。
可以看出,除了两边的点以外,每个点可以上一层的两个位置之一到达当前点。
如果我们知道上一层的从顶端到达两个位置的最大路径值,那么对于当前点来说,必然选择较大的那个位置转移过来,也就得到了顶端到达当前位置的最大值。
以Example_1为例,
dp[1] = 1; dp[2] = dp[1] + 2 = 3; dp[3] = dp[1] + 3 = 4; dp[6] = dp[2] + 6 = 11; dp[5] = max(dp[2], dp[3]) + 5 = 9; dp[4] = dp[3] + 4 = 8;
最长上升子序列
给 个数,求上升子序列的最长长度。
上升子序列,即找到 ,满足
71 7 3 5 9 4 8
最长上升子序列长度为4,其中一种可行的方案为1,3,5,9。
做法
-
表示以第个数结尾的上升子序列的最长长度。
for (int i = 1; i <= n; ++i) { f[i] = 1; for (int j = 1; j < i; ++j) if (a[j] < a[i]) f[i] = max(f[i], f[j] + 1); }
-
对于当前位置的数 来说,就是要找到比它小的数结尾的上升子序列的最长长度,用 表示以数值 结尾的上子序列的最长长度,结合树状数组或者线段树维护区间 的最大长度值即可。
当 比较大(比如)时,需要对数值先进行离散化。
离散化,可以简单地理解为将非常大、不连续的值映射成较小的、连续的值,一一对应。
/** * 离散化 */ vector<int> V; for (int i = 1; i <= n; ++i) V.push_back(a[i]); // 排序 sort(V.begin(), V.end()); // 去重 V.erase(unique(V.begin(), V.end()), V.end()); // 二分映射位置(0 ~ n - 1) for (int i = 1; i <= n; ++i) a[i] = lower_bound(V.begin(), V.end(), a[i]) - V.begin();
背包问题
- 01背包
- 完全背包
- 多重背包
01背包
有一个空间为的背包,有件物品可以选择装入背包,每个物品有价值和体积,求在空间允许的情况下装入的物品价值和最大。
简要分析:在空间固定的情况下,价值肯定越大越好。或者反过来想,在价值固定的情况下,空间越小越好。
// f[i]表示空间为i时的最大价值。 for (int i = 1; i <= n; ++i) // 枚举物品 for (int j = W; j >= w[i]; --j) // 倒着做,避免同一物品装入多次 f[j] = max(f[j], f[j - w[i]] + v[i]);
完全背包
背包空间为,有种物品,每种物品有价值和体积,每种物品有无数件,求背包能装入的最大价值。
简要分析:与01背包的区别在于,一种物品是只有一件还是无数件,01背包是倒着做来避免同一物品装入多次,那么完全背包反过来就可以了。
// f[i]表示空间为i时的最大价值。 for (int i = 1; i <= n; ++i) // 枚举物品 for (int j = w[i]; j <= W; ++j) // 正着做,同一物品可以装入多次 f[j] = max(f[j], f[j - w[i]] + v[i]);
多重背包
多重背包介于01背包和完全背包之间,每种物品的数量限制为个。
分析:对于每种物品,如果把它视为种物品,每种物品只能取一件,就转化成了01背包问题。但是可能非常大,导致复杂度()过高。这时候需要做一些优化工作。已知用1、2、4、8可以组合0~15的任意一个数值。
在二进制下,0~15的数值最多有4位,0000~1111。
而,所以对于0~15的数值化为二进制后根据相应位是否为1就可以知道由1、2、4、8哪些数构成。例如,。
回到背包问题上,我们可以将分成种物品(最多种),每种物品的数量为1,这样理论上可以组合出中的任意数量。时间复杂度降为。
记忆化搜索
本质上还是DP,但是状态之间的转移写成了dfs的形式,所以计算过程中可以减少一些不必要的状态,以及方便边界处理。
POJ 1088 滑雪
Description
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12/ 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Sample Output
25
分析:对当前位置(x, y)来说,当满足高度大小关系的时候,可以连接到(x - 1, y)、(x, y + 1)、(x + 1, y)和(x, y - 1)。
当然可以将所有位置按高度排序,然后按顺序去DP,时间复杂度为
用记忆化搜索的方法做的话,dfs(x, y)表示从(x, y)出发的最长长度,, 当。
因为从(x, y)出发的最长长度是固定的,不存在什么限制条件,所以可以用表示dfs(x, y),令初值为-1,当访问dfs(x, y)时若不为-1,说明计算过了,直接返回即可,这样就避免了重复计算。
当(x, y)超出边界时,直接返回0即可。
动态规划(DP)基础的更多相关文章
- 【专章】dp基础
知识储备:dp入门. 好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了. ----------------------------------------------------------- ...
- 动态规划dp
一.概念:动态规划dp:是一种分阶段求解决策问题的数学思想. 总结起来就一句话:大事化小,小事化了 二.例子 1.走台阶问题 F(10):10级台阶的走法数量 所以:F(10)=F(9)+F(8) F ...
- 算法-动态规划DP小记
算法-动态规划DP小记 动态规划算法是一种比较灵活的算法,针对具体的问题要具体分析,其宗旨就是要找出要解决问题的状态,然后逆向转化为求解子问题,最终回到已知的初始态,然后再顺序累计各个子问题的解从而得 ...
- 【学习笔记】dp基础
知识储备:dp入门. 好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了. dp基础,主要是做题,只有练习才能彻底掌握. 洛谷P1417 烹调方案 分析:由于时间的先后会对结果有影响,所以c[i ...
- hdu 2089 不要62 (数位dp基础题)
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- poj 2955 Brackets (区间dp基础题)
We give the following inductive definition of a “regular brackets” sequence: the empty sequence is a ...
- DP基础(线性DP)总结
DP基础(线性DP)总结 前言:虽然确实有点基础......但凡事得脚踏实地地做,基础不牢,地动山摇,,,嗯! LIS(最长上升子序列) dp方程:dp[i]=max{dp[j]+1,a[j]< ...
- 树形dp基础
今天来给大家讲一下数形dp基础 树形dp常与树上问题(lca.直径.重心)结合起来 而这里只讲最最基础的树上dp 1.选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程 ...
- 动态规划_基础_最长公共子序列_多种方法_递归/dp
D: 魔法少女资格面试 题目描述 众所周知,魔法少女是一个低危高薪职业.随着近年来报考魔法少女的孩子们越来越多,魔法少女行业已经出现饱和现象!为了缓和魔法少女界的就业压力,魔法少女考核员丁丁妹决定增加 ...
- 动态规划DP的优化
写一写要讲什么免得忘记了.DP的优化. 大概围绕着"是什么","有什么用","怎么用"三个方面讲. 主要是<算法竞赛入门经典>里 ...
随机推荐
- .Net Collection的一些理解——记录一次向实习生的答疑
公司最近进了个实习生,每天下班前我都会花一些时间来解答一下实习生的一些疑问.今天问起了关于集合排序方法Sort的一些疑问,这让我一下回到自己刚刚入行的时候.那个时候也遇到了集合排序的问题,为发现接口I ...
- Linux 使用fdisk添加新分区
Linux系统由于数据累计增长.前期存储规划不合理等诸多因素,出现存储不够用的情况时,此时就需要扩展逻辑分区或添加新的逻辑分区.下面介绍一下通过使用fdsik添加新的逻辑分区. 首先使用df命令检查文 ...
- JDBC API Description
package java.sql description What the JDBCTM 4.2 API Includes Versions What the java.sql Package Con ...
- jQuery中多个元素的Hover事件
1.需求简介 jQuery的hover事件只是针对单个HTML元素,例如: $('#login').hover(fun2, fun2); 当鼠标进入#login元素时调用fun1函数,离开时则调用fu ...
- Linux--shell脚本之正则表达式
一.正则表达式的概念及特点: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑.规 ...
- PHP+Apache+Zend Studio+MySql+Navicat+phpAdmin
本文章介绍整个PHP开发环境的搭建 数据库:MySql 5.5.50 数据库软件:Navicat 11.1.20和phpAdmin 4.6.5.1任选 php库:PHP 7.0.13 服务器:Apa ...
- asp.net设置默认打开页面,Web.config,defaultDocument
The web.config file can be used to set a default document, or list of default documents for your web ...
- 推荐一款 chrome SSH 插件 - Secure Shell
http://blog.csdn.net/jizhongchun/article/details/8519413 导读:我就是一个Chrome Fans.最近发现一款google官方出的SSH插件 - ...
- 基于Simple Image Statistics(简单图像统计,SIS)的图像二值化算法。
这是个简单的算法,是全局二值算法的一种,算法执行速度快. 算法过程简单描述如下: 对于每一个像素,做如下处理 1.计算当前像素水平和垂直方向的梯度. (two gradients are calcul ...
- UVALive3902 Network[贪心 DFS&&BFS]
UVALive - 3902 Network Consider a tree network with n nodes where the internal nodes correspond to s ...