动态规划(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的优化. 大概围绕着"是什么","有什么用","怎么用"三个方面讲. 主要是<算法竞赛入门经典>里 ...
随机推荐
- TNS-12518 & Linux Error:32:Broken pipe
最近一周,有一台ORACLE数据库服务器的监听服务在凌晨2点过几分的时间点突然崩溃,以前从没有出现过此类情况,但是最近一周出现了两次这种情况,检查时发现了如下一些信息: $ lsnrctl servi ...
- native2ascii 使用说明
native2ascii.exe 是Java的一个文件转码工具,是将特殊各异的内容转为用指定的编码标准文体形式统一的表现出来,它通常位于JDK_home\bin目录下,安装好Java SE后,可在命令 ...
- mysql 5.5.32 多实例环境的启动问题
[root@localhost scripts]# /bin/sh mysql_install_db --user=mysql --dasedir=/application/mysql --dat ...
- 执行shell脚本,报错坏的解释器
在windows下面用editplus编写了一个shell脚本.执行时报错 "/bin/bash^M: 坏的解释器: 没有那个文件或目录 解决方法: 在终端输入sed -i 's/\r$// ...
- linux ssh和scp实例
ssh 192.160.1.100 -p 40012 scp user 192.169.72.2:/ scp -i /id_rsa -P40027 root@221.212.235.17:/sdzw/ ...
- 1 张图秒懂 Nova 16 种操作 - 每天5分钟玩转 OpenStack(44)
前面我们讨论了 Instance 的若干操作,有的操作功能比较类似,也有各自的适用场景,现在是时候系统地总结一下了. 如上图所示,我们把对 Instance 的管理按运维工作的场景分为两类:常规操作和 ...
- Java中图片压缩处理
原文http://cuisuqiang.iteye.com/blog/2045855 整理文档,搜刮出一个Java做图片压缩的代码,稍微整理精简一下做下分享. 首先,要压缩的图片格式不能说动态图片,你 ...
- Android入门笔记(一)
第一部分,Android开发环境的搭建 1.去http://www.oracle.com/technetwork/java/javase/downloads/index.html下载最新版本jdk并安 ...
- 浏览器请求页面时Etag和cache的区别
etag:简单的说就是服务器收到客户端的请求后,根据返回的内容计算出来一个etag值,返回给客户端,当客户端下次再请求相同路径的时候会带上之前的etag值,服务器端会根据这次请求应该返回的内容计算出新 ...
- 【Windows编程】系列第三篇:文本字符输出
上一篇我们展示了如何使用Windows SDK创建基本控件,本篇来讨论如何输出文本字符. 在使用Win32编程时,我们常常要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接 ...