动态规划算法
动态规划算法
1. 算法介绍
动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题,进行解决,从而一步步获取最优解的处理算法
其算法思想与分治法类似,与分治法不同的是,适合于动态规划求解的问题,经过分解得到的子问题往往不是独立的(下一个子阶段的求解是建立在上一个子阶段和解的基础上,进行进一步的求解)
动态规划可以通过填表的方式来逐步推进,得到最优解
2. 应用场景-背包问题
背包问题:在重量不超出的情况下,装入物品不重复的情况下,装入总价值最大!
| 物品 | 重量 | 价格 |
|---|---|---|
| 吉他 | 1 | 1500 |
| 音响 | 4 | 3000 |
| 电脑 | 3 | 2000 |
3. 算法思路
- 每次遍历第 i 个物品,根据w[i] 与 v[i] 来确定是否需要将该物品放入背包中
- 即对于给定的 n 个物品,设v[i]、w[i]分别为第 i 个物品的价值和重量,C为背包的容量。
- 再令v[i] [j]表示在前 i 个物品中能够装入容量为 j 的背包中的最大价值。
v[i][0] = v[0][j] = 0
w[i] > j时: v[i][j] = v[i - 1][j]
j >= w时:v[i][j] = max[v[i - 1][j]]
i:商品号
j:背包容量
v[i]: i 商品的价值
w[i]: i 商品的重量
v[i][j]:表示在前 i 个物品中能够装入容量为j的背包中的最大价值
v[i - 1][j]:上一个单元格装入的最大值
v[i - 1][j - w[i]]:装入 i - 1 商品,到剩余空间 j - w[i]的最大值
4. 代码实现
package cn.imut;
public class KnapsackProblem {
public static void main(String[] args) {
int[] w = {1, 4, 3}; //物品的重量
int[] val = {1500, 3000, 2000}; //物品的价值
int m = 4; //背包容量
int n = val.length; //物品的个数
//v[i][j]表示前 i 个物品能够装入容量为 j 的背包的 最大价值
int[][] v = new int[n + 1][m + 1];
//记录放入商品的情况
int[][] path = new int[n + 1][m + 1];
//初始化
for(int i = 0; i < v.length; i++) {
v[i][0] = 0; //将第一列设为 0
}
for(int j = 0; j < v.length; j++) {
v[0][j] = 0; //将第一行设为 0
}
//动态规划处理
for (int i = 1; i < v.length; i++) { //不处理第一行 i 从 1开始
for(int j = 1; j < v[0].length; j++) { //不处理第一列,j 从 1开始
if(w[i - 1] > j) {
v[i][j] = v[i - 1][j];
}else {
if(v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
//将情况记录到path
path[i][j] = 1;
}else {
v[i][j] = v[i - 1][j];
}
}
}
}
//输出v,查看目前情况
for (int[] ints : v) {
for (int anInt : ints) {
System.out.println(anInt + " ");
}
System.out.println();
}
System.out.println("=======================");
int i = path.length - 1;
int j = path[0].length - 1;
while (i > 0 && j > 0) {
if(path[i][j] == 1) {
System.out.printf("第%d个商品放入背包\n", i);
j -= w[i - 1];
}
i--;
}
}
}



浙公网安备 33010602011771号