动态规划的基本思想是通过子问题的结果推导出问题结果。先把子问题结果都保存起来,要求问题结果时,从保存的结果里找到之前的结果组合成新问题的结果。同时遵循自左向右,自下而上。
斐波那契
F(n)= F(n-1)+F(n-2)是问题结果的推导。n时的结果是n-1的结果加n-2的结果。用数组来保存之前的结果,要求N时,就去数组里拿。
这题也能用递归求解,但耗时过长。每次递归都要重新计算结果。
```java
class Solution {
public int fib(int n) {
/** 动态规划思想,初始化dp数组保存每个子问题的解。直接根据数组计算下个结果**/
if(n==0){
return 0;
}
if(n==1){
return 1;
}
// 结果数组
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
for(int i = 2;i <=n;i++){
dp[i] = (dp[i-1]+dp[i-2]) %1000000007;
}
return dp[n];
}
}
青蛙跳台阶
要求n级台阶跳的次数。要知道青蛙最后一次跳台阶,要么跳一格要么跳二格。当跳一格时,那他已经跳了n-1格台阶,也就是有f(n-1)种方法跳到n-1级台阶。当跳两格时,那他已经跳了n-2格同理就是f(n-2)。进而发f(n)=f(n-2)+f(n-1)
class Solution {
public int numWays(int n) {
if(n == 0){
return 1;
}
if(n == 1){
return 1;
}
int[] res = new int[n+1];
res[0] = 1;
res[1] = 1;
for(int i=2;i<=n;i++){
res[i] = (res[i-1]+res[i-2]) % 1000000007;
}
return res[n];
}
}
01背包
给定 n 个物品和一个容量为 W 的背包,物品 i 的重量是 wi,其价值为 vi 。应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?
(输出给定n和W时的最大总价值)
例:
有如下5个物品,小明的书包最多只能装下8公斤的物品,小明特别贪心,思考怎么选择使自己书包能装下并且得到的价值最大。
物品1:6公斤 价值48元
物品2:1公斤 价值7元
物品3:5公斤 价值40元
物品4:2公斤 价值12元
物品5:1公斤 价值8元
建立二维表,行代表背包容量。列代表可以放入的物品。遵循自左向右自下而上。从左下角开始填表,当背包容量为1kg和有物品5的情况下,最大价值就是8元。当背包容量为1kg和有物品4、物品5的情况下,最大价值为12元。
逐步将问题抽象为,第n件物品放还是不放的问题。以上图表格为例。现在要求行为2,列为3的值。也就是背包容量为3kg,可放物品有2、3、4、5。
如果物品2不放,就是求背包容量为3kg,可放物品有3、4、5的值,也就是标黄格子的值。
如果物品2放,要把物品2的1kg空出来,背包也就只有2kg,可放物品为3、4、5。也就是红格子所代表的值。拿红格子的值加要放入背包的物品2的值就是这个子问题的解。
最后比较这两个子问题,哪个大就选哪个。