概念理解
动态规划是从小问题着手,逐步解决大问题,每次决策依赖于当前的状态 进而引起状态的转移,把一个问题拆分成子问题的一种思想,利用二维的思想在解决生活中的各种问题。
举个例子:假设你明天要去户外,你有一个背包,容量只有4千克。你可盗窃的东西有三件:
为了让你的背包装的东西价值最高,你会怎样选择:
最简单的算法是,尝试各种商品的组合,并找出价值最高的组合。
这样可行,但是非常慢,试想一下,3件商品需要计算8中不同的组合,如果4 件 那你需要2^4种组合,每增加一种商品 计算的范围将扩大一倍。时间复杂度O(n^2),慢如蜗牛。只要商品数量扩大到一定程度,这种该算法行不通。
当然,答案是使用动态规划,每个动态规划算法都是从一个网格开始,网格如下:
网格的各行为商品,你都需要,各列为不通容量(1~4)的背包,所有这些列你也都需要,因为将帮助你计算子背包的价值。
1.手机行
我们先一步一步做,首先看第一行,你将尝试将它装入背包,在每一个单元格,你都需要做一个简单的决定,装不装手机,别忘了,你要找出一个价值最高的商品组合.第一各单元格的背包容量为1kg,手机重量也是1kg,能装入背包,因此装入,价值为1500元因此填入:
再看下一个,背包容量为2kg,饼干为1kg 完全可以装得下,这行的其他单元格也一样,因为这一行只有饼干可供选择,假设其他商品还没有来得及装。因此 网格变为如下:
你的目的是让背包中商品价值最大化,这行表示当前最大值,当然,你知道这并不是最优解,随算法的往下执行,你将逐步计算并修改最大价值。我们再看
该不该装大桶水呢,背包容量为1kg,税太重了 装不下 看下一个 背包容量为2kg 同样装不下,容量为3kg 也装不下,容量为4kg 刚好能装下,而且价值最高,因此网格变为:
你更新了最大值,因此下面 你逐步更新最大值,用同样的方法来处理手机行,手机重3kg,没法装入,容量为1kg 2kg的背包,因此 前两个单元格的最大价值依然是1500元,
当背包容量为3kg时,原来的最大价值时1500元,但是现在你可以选择装入价值3000元的大包饼干,因此,更新最大价值为3000元,
对于容量为4kg的背包,情况有趣,也非常重要,当前的最大价值为4000元.你可以不装大桶水,只装饼干 价值只有3000元 4000 > 3000 价值没有原来高,但想一想,饼干重量只有3kg,还剩1kg容量没有使用! 在1kg容量中 可装入的最大价值是多少呢?根据之前计算的最大价值可知,1kg背包可装入的最大价值是手机 1500元,因此,你需要做如下比较:
4000 vs 3000+1500 ?
因此 网格的最终计算结果如下:
确定最终答案 装入手机和大包饼干 价值最大。
其实,在计算每一个单元格时 都使用了相同的公式:
同样,
有数组nums,nums中所有的值都为正数且不重复,每种面值的货币可以使用任意次,再给定一个整数capacity(小于等于1000)为和,能有多少种计算方法。
给定数组nums及它的大小(小于等于100),同时给定一个整数capacity,请返回有多少种方法相加等于capacity。
测试样例:
[1,3,5],3,8
返回:5
解析:设tmp[n][m]为使用前n中凑成的m的种数,那么就会有两种情况:
使用第n种:tmp[n-1][m]+tmp[n][m-nums[n]]
不用第n种:tmp[n-1][m],为什么不使用第n种呢,因为nums[n]>m。
这样就可以求出当m>=nums[n]时 tmp[n][m] = tmp[n-1][m]+tmp[n][m-nums[n]],否则,tmp[n][m] = tmp[n-1][m]