【转】动态规划DP
【数据结构与算法】 DP 动态规划 介绍
原创 2017年02月13日 00:42:51
最近在看算法导论。
DP全称是dynamic programming,这里programming不是编程,是一个表格保存之前的结果。
DP 是一种编程思想,主要用于解决最优解类型的问题。
其思路是为了求解当前的问题的最优解,使用子问题的最优解,然后综合处理,最终得到原问题的最优解。
但是也不是说任何最优解问题都可以DP,使用dp的问题一般满足下面的两个特征:
(1)最优子结构,就是指问题可以通过子问题最优解得到;体现为找出所有的子问题最优解,然后取其中的最优;
(2)重叠子问题,就是子问题是会重复的。而不是一直产生新的子问题(比如分治类型的问题)。
一般而言,满足上述两个条件的最优解问题都可以会使用DP来解决。
DP在算法上的形式是什么?
有两种,一种是自顶向下,就是直接从原问题入手,不断利用子问题来求解,这种写法是一个递归地形式,但是需要加入备忘录,就是说利用一个数组存已经算出的子问题的结果,下次遇到直接返回。这个思路叫做memoization,备忘录。是一种空间换时间的做法,因为某些子问题会被调用到很多次,如果使用memo,那么时间上会很高效。比如求斐波那契数列,几乎每一个求解都会用到f(2)这样的子问题,如果事先存好,那么时间复杂度会下降很多。还有一点,memo不是为dp而生的,它也是一种思想或者技巧,在递归或者dfs中可以使用,如果要求时间复杂度可以考虑使用memo。
第二种是自底向上,这种不需要递归,就是不断地计算出小问题的解,然后后面的问题就可以利用小问题的解得到。
下面是算法导论中的一个简单的例子,给出一个长度为n的钢管,然后给出切割为不同长度以后的价格,问如何切割获利最大。
/**
* @author miracle
*切割钢条问题:
*长度:1 2 3 4 5 6 7 8 9 10
*价格:1 5 8 9 10 17 17 20 24 30
*问长度为n的钢条的最多卖多少钱
*/
public class Solution {
int[] prices = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
int[] dp = new int[prices.length];
public int solve(int[] prices, int n){
if(n == 0) return 0;
int max = Integer.MIN_VALUE;
for(int i = 1; i <= n; i++){
max = Math.max(max, prices[i] + solve(prices, n - i));
}
return max;
}
public int solveWithMemoUpToBottom(int[] prices, int n){
if(n == 0 || dp[n] > 0) return dp[n];
int max = Integer.MIN_VALUE;
for(int i = 1; i <= n; i++){
max = Math.max(max, prices[i] + solve(prices, n - i));
}
dp[n] = max;
return max;
}
public int solveBottomToUp(int[] prices, int n){
int[] dp = new int[prices.length];
for(int i = 1; i <= n; i++){
int max = Integer.MIN_VALUE;
for(int j = 1; j <= i; j++){
max = Math.max(max, prices[j] + prices[i - j]);
}
dp[i] = max;
}
return dp[n];
}
public static void main(String args[]){
Solution s = new Solution();
// System.out.println(s.solve(s.prices, 1));
// System.out.println(s.solve(s.prices, 2));
// System.out.println(s.solve(s.prices, 3));
// System.out.println(s.solve(s.prices, 4));
// System.out.println(s.solve(s.prices, 5));
System.out.println(s.solveBottomToUp(s.prices, 1));
System.out.println(s.solveBottomToUp(s.prices, 2));
System.out.println(s.solveBottomToUp(s.prices, 3));
System.out.println(s.solveBottomToUp(s.prices, 4));
System.out.println(s.solveBottomToUp(s.prices, 5));
}
}
分别给出了不带memo,带memo的以及自底向上3中算法。
就实际情况来看,一般还是使用非递归的bottom to up类型。但是memo在递归中的使用也是一个小的技巧。
最后说下递归,dp,分治的区别。
递归只是一种编程的思想,只要自己调用自己,就算是递归。
分治,有三步,先分,再各自处理,最后整合。这里也涉及了子问题,这里的子问题是不重叠的,每一个只被处理一次,因此不需要memo。
dp,可以使用递归,而且dp的子问题是重复的。
dp说白了是子问题或者递归+memo,他其实是一种brute force,只不过记录了全部的结果,这就是为什么dp适用于解决最优解问题的原因(开头提到),其实它不一定非得解决最优解,只是它的思想使得它非常适合解决最优解问题。
【转】动态规划DP的更多相关文章
- 动态规划dp
一.概念:动态规划dp:是一种分阶段求解决策问题的数学思想. 总结起来就一句话:大事化小,小事化了 二.例子 1.走台阶问题 F(10):10级台阶的走法数量 所以:F(10)=F(9)+F(8) F ...
- 算法-动态规划DP小记
算法-动态规划DP小记 动态规划算法是一种比较灵活的算法,针对具体的问题要具体分析,其宗旨就是要找出要解决问题的状态,然后逆向转化为求解子问题,最终回到已知的初始态,然后再顺序累计各个子问题的解从而得 ...
- 动态规划DP的优化
写一写要讲什么免得忘记了.DP的优化. 大概围绕着"是什么","有什么用","怎么用"三个方面讲. 主要是<算法竞赛入门经典>里 ...
- hdu 1421:搬寝室(动态规划 DP + 排序)
搬寝室 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- hdu 2059:龟兔赛跑(动态规划 DP)
龟兔赛跑 Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submissi ...
- Luogu 2627 修建草坪 (动态规划Dp + 单调队列优化)
题意: 已知一个序列 { a [ i ] } ,求取出从中若干不大于 KK 的区间,求这些区间和的最大值. 细节: 没有细节???感觉没有??? 分析: 听说有两种方法!!! 好吧实际上是等价的只是看 ...
- 动态规划DP入门
百度百科↓ 动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法.20世纪50年代初美国数学家R.E.Bellman ...
- hdu 1087 Super Jumping! Jumping! Jumping!(动态规划DP)
Super Jumping! Jumping! Jumping!Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- nyoj 16-矩形嵌套(贪心 + 动态规划DP)
16-矩形嵌套 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:13 submit:28 题目描述: 有n个矩形,每个矩形可以用a,b来描述,表示长和 ...
随机推荐
- spring9——AOP之AspectJ对AOP的实现
从上述的实验中可以看出BeanNameAutoProxyCreator对于AOP的实现已经和完美了,但是还有两点不足之处: 1,对于切面的实现比较麻烦,既不同类型的通知切面要实现不同的接口,而且一个切 ...
- 使用nodeJS的 crypto模块来为你的密码hash加盐
这篇文章将向你解释如何使用Node.js的Crypto模块对你的密码进行加盐hash.在这里,我们将不会对不懂的密码存储方式进行详细的比较.我们将要做的是知道在Node.js中使用加盐hash在进行密 ...
- MySQLdb、 flask-MySQLdb 、MySQL-python 安装失败
今天在学习flask的时候,学习到数据库部分,连接mysql生成表,运行程序报错误:No module named MySQLdb 此时 需要安装 以下两个中任何一个 pip install flas ...
- mangodb的基本操作:增删改差
MongoDB三元素: 1 数据库: 和关系型数据库中数据库的层次相同,内部可以有多个集合. 2 集合: 相当于关系型数据库中的表,存储若干文档,结构不固定 3 文档: 相当于关系型数据库中的行,是J ...
- Spring之AOP编程
一.AOP简介 AOP的英文全称是Aspect Oriented Programming,意为:面向切面编程. AOP采取横向抽取的机制,取代了传统纵向继承体系的代码复用.AOP常用于 ...
- JAVA通过注解处理器重构代码,遵循单一职责
前言:最近在看一个内部网关代码的时候,发现处理Redis返回数据这块写的不错,今天有时间好好研究下里面的知识点. 业务流程介绍: #项目是采用Spring Boot框架搭建的.定义了一个@Redis注 ...
- POJ-3259 Wormholes---SPFA判断有无负环
题目链接: https://vjudge.net/problem/POJ-3259 题目大意: 农夫约翰在探索他的许多农场,发现了一些惊人的虫洞.虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的 ...
- Spring之事务管理
事务管理对于企业应用至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性. 就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到 ...
- javascript实现有限状态机
1.状态机描述 简单说,有限状态机是一种模型,模型都用来模拟事物,能够被有限状态机这种模型模拟的事物,一般都有以下特点: 1)可以用状态来描述事物,并且任一时刻,事物总是处于一种状态: 2)事物拥有的 ...
- python pygame 安装和运行的一些问题
1.python安装过程中可以选择自动配置环境变量,可以避免手动配置,但是缺点是如果环境变量有问题,就得自己重新学习配置环境变量. 2.我自己想用python从游戏方面入手,所以在安装pygame过程 ...