如果要求一个问题的最优解(通常是最大值或者最小值),而且该问题能够分解成若干个子问题,并且小问题之间也存在重叠的子问题,则考虑采用动态规划。
使用动态规划特征:
1. 求一个问题的最优解
2. 大问题可以分解为子问题,子问题还有重叠的更小的子问题 ,即整体问题最优解取决于子问题的最优解(状态转移方程) 。
3. 从上往下分析问题,从下往上解决问题
4. 讨论底层的边界问题
例1:硬币问题
我们有面值为1元3元5元的硬币各无数枚,如何用最少的硬币凑够21(这个值可以随意指定)元?
分析:
1. 求问题的最优解:最小的硬币数
2. 是否有子问题:假设f(n)表示凑够n元的最少硬币数。则显然,f(n)=min(f(n-1),f(n-3),f(n-5)) + 1;
3. 确定最小问题的解。
f(1)=1, f(2)=2, f(3)=1,f(4)=2, f(5)=1
5 从上往下分析问题,从下往上解决问题。
代码:
package dataStructureAndAlgorithms; public class DaymicPrograming { //递归方法 public static int findMinCoinNumberByRecursion(int n){ if(n == 1 || n == 3 || n == 5){ return 1; } if(n == 2 || n == 4){ return 2; } return min(findMinCoinNumberByRecursion(n-1),findMinCoinNumberByRecursion(n-3),findMinCoinNumberByRecursion(n-5)) + 1; } //从下往上的方法 public static int findMinCoinNumberFromDownToUp(int n){ int size = n>5?n:5; int[] minNumber = new int[size+1]; minNumber[1] = minNumber[3] = minNumber[5] = 1; minNumber[2] = minNumber[4] = 2; for(int i=6;i<=n;i++){ minNumber[i] = min(minNumber[i-1],minNumber[i-3],minNumber[i-5]) + 1; } return minNumber[n]; } public static int min(int a, int b, int c){ return a<b?(a<c?a:c):(b<c?b:c); } public static void main(String[] args) { for(int i=5;i<=30;i++){ System.out.print("数额:" + i + ",递归算法计算出 最少硬币数:" + findMinCoinNumberByRecursion(i)); System.out.println(", 从下往上的方法计算出最少硬币数:" + findMinCoinNumberFromDownToUp(i)); } } }
结果:
数额:5,递归算法计算出 最少硬币数:1, 从下往上的方法计算出最少硬币数:1 数额:6,递归算法计算出 最少硬币数:2, 从下往上的方法计算出最少硬币数:2 数额:7,递归算法计算出 最少硬币数:3, 从下往上的方法计算出最少硬币数:3 数额:8,递归算法计算出 最少硬币数:2, 从下往上的方法计算出最少硬币数:2 数额:9,递归算法计算出 最少硬币数:3, 从下往上的方法计算出最少硬币数:3 数额:10,递归算法计算出 最少硬币数:2, 从下往上的方法计算出最少硬币数:2 数额:11,递归算法计算出 最少硬币数:3, 从下往上的方法计算出最少硬币数:3 数额:12,递归算法计算出 最少硬币数:4, 从下往上的方法计算出最少硬币数:4 数额:13,递归算法计算出 最少硬币数:3, 从下往上的方法计算出最少硬币数:3 数额:14,递归算法计算出 最少硬币数:4, 从下往上的方法计算出最少硬币数:4 数额:15,递归算法计算出 最少硬币数:3, 从下往上的方法计算出最少硬币数:3 数额:16,递归算法计算出 最少硬币数:4, 从下往上的方法计算出最少硬币数:4 数额:17,递归算法计算出 最少硬币数:5, 从下往上的方法计算出最少硬币数:5 数额:18,递归算法计算出 最少硬币数:4, 从下往上的方法计算出最少硬币数:4 数额:19,递归算法计算出 最少硬币数:5, 从下往上的方法计算出最少硬币数:5 数额:20,递归算法计算出 最少硬币数:4, 从下往上的方法计算出最少硬币数:4 数额:21,递归算法计算出 最少硬币数:5, 从下往上的方法计算出最少硬币数:5 数额:22,递归算法计算出 最少硬币数:6, 从下往上的方法计算出最少硬币数:6 数额:23,递归算法计算出 最少硬币数:5, 从下往上的方法计算出最少硬币数:5 数额:24,递归算法计算出 最少硬币数:6, 从下往上的方法计算出最少硬币数:6 数额:25,递归算法计算出 最少硬币数:5, 从下往上的方法计算出最少硬币数:5 数额:26,递归算法计算出 最少硬币数:6, 从下往上的方法计算出最少硬币数:6 数额:27,递归算法计算出 最少硬币数:7, 从下往上的方法计算出最少硬币数:7 数额:28,递归算法计算出 最少硬币数:6, 从下往上的方法计算出最少硬币数:6 数额:29,递归算法计算出 最少硬币数:7, 从下往上的方法计算出最少硬币数:7 数额:30,递归算法计算出 最少硬币数:6, 从下往上的方法计算出最少硬币数:6