背包问题的思路整理
package algorithm;
import java.util.Arrays;
public class Backpack {
/*
* 物品 1 2 3 4 5
* 价值 60 100 120 61 131
* 重量 1 2 4 1 4
*/
// 物品价值
static int[] value = { 60, 100, 120, 61, 131};
// 物品重量
static int[] weight = { 1, 2, 4, 1, 4 };
// 背包总重量
static int w = 5;
// 物品个数
static int n = value.length;
// 动态规划记录表
static int[][] dpRecord = new int[n + 1][w + 1];
public static void main(String[] args) {
// 动态规划执行运算
backpack();
// 打印结果
printResult();
// 最优解的执行路径
calcPath();
}
// 动态规划
public static void backpack() {
// 依次加入物品
for (int i = 1; i <= n; i++) {
// 当前物品的价值
int valueTemp = value[i - 1];
// 当前物品的重量
int weightTemp = weight[i - 1];
// 分割的背包栏
for (int cw = 1; cw <= w; cw ++) {
// 如果当前物品重量小于等于当前能承载的总重量 拥有选择权
if(weightTemp <= cw) {
// 选择后剩余重量
// cw - weightTemp;
// 剩余重量对应的最大价值
int leftMaxValue = dpRecord[i - 1][cw - weightTemp];
// 选择
// 本次价值 + 剩余重量 对应的最大价值
int choseValue = valueTemp + leftMaxValue;
// 不选择
// 剩余重量对应的最大价值 dpRecord[i - 1][cw]
// 添加记录项
dpRecord[i][cw] = max(choseValue, dpRecord[i - 1][cw]);
}else {
// 如果当前物品重量已经大于当前能承载的总重量 只能不选
dpRecord[i][cw] = dpRecord[i - 1][cw];
}
}
}
}
// 打印结果
public static void printResult() {
for (int i = 0; i < dpRecord.length; i++) {
System.out.println(Arrays.toString(dpRecord[i]));
}
System.out.println("最优解:" + dpRecord[n][w]);
}
// 求得最优解的执行路径
public static void calcPath() {
System.out.println("=====求得最优解的执行路径=====");
int leftWeight = w;
for (int i = dpRecord.length - 1; i > 0; i--) {
if(dpRecord[i][leftWeight] != dpRecord[i - 1][leftWeight]) {
System.out.println(value[i - 1] + "\t被选中");
leftWeight -= weight[i - 1];
}
}
}
// 返回两数中最大值
public static int max(int m,int n) {
return m > n ? m : n ;
}
}
附执行结果如下:
[0, 0, 0, 0, 0, 0]
[0, 60, 60, 60, 60, 60]
[0, 60, 100, 160, 160, 160]
[0, 60, 100, 160, 160, 180]
[0, 61, 121, 161, 221, 221]
[0, 61, 121, 161, 221, 221]
最优解:221
=====求得最优解的执行路径=====
61 被选中
100 被选中
60 被选中