动态规划(dynamic programming)
概念
可以将一个复杂的大问题分解为简单的小问题,通过求解小问题来得出大问题的解。
性质
无后效性:某一阶段状态确定之后,这阶段之后的发展不受这阶段以前各阶段的状态影响。即未来与过去无关
最优子结构:大问题的最优解可以由小问题的最优解推出
重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。
适用范围
具有重叠子问题和最优子结构性质的问题
分治与动态规划的区别
共同点:二者都要求原问题具有最优子结构性质,都是将原问题分而治之,分解成若干个规模较小(小到很容易解决的程序)的子问题.然后将子问题的解合并,形成原问题的解.
不同点:分治法将分解后的子问题看成相互独立的,通过用递归来做。
动态规划将分解后的子问题理解为相互间有联系,有重叠部分,需要记忆,通常用迭代来做。
步骤
- 问题抽象
- 建模(最终要求什么)
- 约束条件(满足什么样的条件)
- 确定具有最优子结构
- 定义状态
- 大问题和小问题状态转移方程
- 填表
- 根据表的结果寻求解的组成
问题1:0-1背包问题
有n 个物品,它们有各自的大小和价值,给定容量cap的背包,如何让背包里装入的物品具有最大的价值总和?
分析步骤
问题抽象:对于每个物品,都有可能要或者不要,因此采用(X1,X2,...Xi,...,Xn)代表第i个物品要或者不要。每个物品的价值为Vi,每个物品的大小为Wi。
建模:最大化价值。max(sum(Xi * Vi))。
约束条件:sum(Xi * Wi) < cap
最优子结构:对每一阶段均可表示成前i个物品组合是否可以使当前阶段总价值最大,这一问题在不同的阶段均适用。
定义状态:V(i,j)--前i个物品最佳组合的总价值,i--表示前i个物品,j--表示剩余容量
状态转移方程:对第i个物品,有两个选择--要或者不要。要--不一定当前总价值最大;不要--最大价值等于前一阶段总价值。
判断条件为--均不能超过剩余背包容量。
V(i,j) = V(i -1,j) , Wi > j; -- 不要第i个物品
V(i,j) = max{V(i -1,j - Wi) + Vi , V(i -1,j)} , Wi <= j; -- 要第i个物品
static int[][] findMax(int cap, int n, int[] value, int[] weight, int[] item){
int[][] v = new int[n + 1][cap + 1]; //建立路由表
//首先初始化第一列第一行
for (int i = 0; i < v.length; i++) {
v[i][0] = 0;
}
for (int i = 0; i < v[0].length; i++) {
v[0][i] = 0;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= cap; j++) {
if(weight[i - 1] > j) { //大小和价值数组均要减1才能不越界
v[i][j] = v[i - 1][j];
}else {
if(v[i - 1][j] < (v[i - 1][j - weight[i - 1]] + value[i - 1])) {
v[i][j] = v[i - 1][j - weight[i - 1]] + value[i - 1];
}
else {
v[i][j] = v[i - 1][j];
}
}
}
}
return v;
}
public static void main(String[] args) {
int n = 4;
int cap = 8;
int[] value = new int[n];
int[] weight = new int[n];
System.out.println("请输入每个物品的价值:");
for(int i = 0; i < n; i++) {
Scanner in = new Scanner(System.in);
if(in.hasNextInt())
value[i] = in.nextInt();
}
System.out.println("请输入每个物品的大小:");
for(int i = 0; i < n; i++) {
Scanner in = new Scanner(System.in);
weight[i] = in.nextInt();
}
int[] item = new int[n];
int[][] res = findMax(cap, n, value, weight,item);
System.out.println(res[n][cap]);
}
参考:
https://www.cnblogs.com/raichen/p/5772056.html
https://www.zhihu.com/question/23995189/answer/613096905
https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html