动态规划算法一般用于求解具备某种最优性质的问题。在这类问题中, 可能会有不少可行解。每个解都对应于一个值,咱们但愿找到具备最优值的解。动规划算法与分治法相似,其基本思想也是将待求解问题分解为若干个子问题,先求解子问题,而后从这些子问题的解获得原问题的解。与分治法不一样的是,适用于动态规划算法求解的问题,经分解获得的子问题每每不是互相独立的。若用分治法来解这类问题,则分解获得的子问题数目太多,有些子问题被重复计算不少次。若是咱们能保存已解决子问题的答案,而在须要时再找出已求得的答案,这样就能够避免大量的重复计算,节省时间。咱们能够用一个表来记录全部已解决的子问题的答案。无论该子问题之后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划算法的基本思路。具体的动态规划算法多种多样,但它们具备相同的填表格式。ios
与分治法最大的差异是:适用于动态规划求解的问题,经分解后获得的子问题不是互相独立的(即下一个子阶段的求解是创建在上一个子阶段的解的基础上,进行进一步的求解)c++
适用于动态规划的问题必须知足最优化原理、无后效性和重叠性。算法
(1) 最优化原理(最优子结构性质):一个最优化策略具备这样的性质,不论过去状态和决策如何,对前面的决策所造成的状态而言,余下的决策必须构成最优策略。简而言之,一个最优化策略的子策略老是最优的。一个问题知足最优化原理又称其具备最优子结构性质。优化
(2) 无后效性:将各阶段按照必定的次序排列好以后,对于某个给定的阶段状态,它之前各阶段的状态没法直接影响它将来的决策,而只能经过当前的这个状态。换句话说,每一个状态都是过去历史的一个完整总结。这就是无后向性,又称无后效性。spa
(3) 子问题的重叠性:动态规划将原来具备指数级时间复杂度的搜索算法改进成了具备多项式时间复杂度的算法。其中的关键在于解决冗余,这就是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程当中,不得不存储产生过程当中的各类状态,因此它的空间复杂度要大于其余算法。.net
有编号分别为a,b,c,d,e的五件物品,它们的重量分别是4, 6, 2, 2, 5, 1,它们的价值分别是8, 10, 6, 3, 7, 2,每件物品数量只有一个,如今给你个承重为12的背包,如何让背包里装入的物品具备最大的价值总和?3d
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; void dynamic(int N, int C, int* weight, int* value) { int* arr = new int[C+1]; int* prearr = new int[C+1]; int* maxvalue = new int[N]; for (int i=1; i<=C; i++) { prearr[i] = 0; } for (int n=0; n<N; n++) { for (int c=1; c<=C; c++) { if (weight[n] > c) { arr[c] = prearr[c]; } else { arr[c] = max(prearr[c], prearr[c-weight[n]]+value[n]); } } maxvalue[n] = arr[C]; for (int i=1; i<=C; i++) { prearr[i] = arr[i]; printf("%3d ", prearr[i]); } cout << endl; } for (int i=1; i<=C; i++) { printf("%3d ", prearr[i]); } cout << endl; for (int i=N-1; i>0; i--) { if (maxvalue[i] != maxvalue[i-1]) { cout << i << '\t'; } } if (maxvalue[0] != maxvalue[1]) { cout << 0 << endl; } delete[] arr; delete[] prearr; delete[] maxvalue; } int main() { int weight[] = {4, 6, 2, 2, 5, 1}; int value[] = {8, 10, 6, 3, 7, 2}; dynamic(6, 12, weight, value); return 0; }
运行结果:blog
0 0 0 8 8 8 8 8 8 8 8 8 0 0 0 8 8 10 10 10 10 18 18 18 0 6 6 8 8 14 14 16 16 18 18 24 0 6 6 9 9 14 14 17 17 19 19 24 0 6 6 9 9 14 14 17 17 19 21 24 2 6 8 9 11 14 16 17 19 19 21 24 2 6 8 9 11 14 16 17 19 19 21 24 2 1 0
有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。一共有多少种走法。博客
分析:it
若是只差最后一步走到第10级台阶,这时候,会出现两种状况:
1. 从第9级走1步到第10级
2. 从第8级走2步到第10级
若是咱们已经知道0到9级走法有X种,0到8级走法有Y种,那么0到10级走法 X+Y 种
咱们把走到第n级表示为 F(n),则
F(10) = F(9) + F(8)
当只有1级台阶和两级台阶,走法分别为 1 和 2
可得:
F(1) = 1
F(2) = 2
F(n) = F(n-1) + F(n-2) (n>=3)
动态规划中包含三个重要概念:最优子结构,边界,状态转移方程
其中,F(9) 和 F(8) 就是 F(10) 的最优子结构,F(1) 和 F(2) 是问题的边界
F(n) = F(n-1) + F(n-2) 是状态转移方程
该祭出表格了:
台阶数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
走法数 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | ... |
参考博客:
https://blog.csdn.net/wangbaochu/article/details/53099953
https://blog.csdn.net/na_beginning/article/details/62884939