- 动态规划过程:
每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
- 基本思想:
将待求解的问题分解为若干个阶段,按顺序求解子阶段,前一子阶段的解,为后一子阶段的求解提供了有用的信息,存在一定的递推关系。即可以由(n-1)的最优推导出n的最优。
- 基本做法:
1.划分阶段,寻找从前一个阶段转化到后一个阶段之间的递推关系
2.把子阶段信息保存在一个数组中(一维,二维或 三维)
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个数组中。
- 什么时候用动态规划:
- 动态规划应用1--01背包问题
有N件物品和一个容量为V的背包,第i件物品的体积是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
解析:
这是最基础的背包问题,特点是每种物品仅有一件,可以选择放或不放。用子问题定义状态,即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。其状态转移方程便是f[i][v] = max{f[i-1][v], f[i-1][v-c[i]]+w[i]},这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的,所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只关系前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,其价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。算法实现:
#include<stdio.h> #include<string.h> #define N 1000 int f[N][N]; int main() { int w[N], c[N], i, j, n, v; // 输入物品的个数;输入背包的体积 scanf_s("%d%d", &n, &v); // 输入n种物品的价值; for(i = 1; i <= n; i++) scanf_s("%d", &w[i]); // 输入n种物品的体积 for(i = 1; i <= n; i++) scanf_s("%d", &c[i]); // 初始化数组f的元素为0 memset(f, 0, sizeof(f)); for(i = 1; i <= n; i++) for(j = 0; j <= v; j++) { // 如果当前物品的体积小于背包体积, // 且当前物品的价值加上背包剩下的空间能放下的物品的价值大于上一次选择的最佳方案,则更新f[i][