目录
思路
问题引出
代码实现
public class PackageSackProblem {
public static void main(String[] args) {
int[] w = {1, 4, 3};// 给定物品重量
int[] val = {1500, 3000, 2000};// 给定物品价格
int n = val.length; // 物体总数
int m = 4; //背包总重
int[][] v = new int[n + 1][m + 1];// 给定表格, 行数为物品数 +1, 列为总重 +1;
int[][] path = new int[n + 1][m + 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;
}
// 开始填表
// 行和列都不从第一行或列开始, 因为第一行默认为零
// 但是也存在问题, 对应的 物品重量(w) 和 物品价格(val) 要i - 1 对应第一位
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
if(w[i - 1] > j){
// 当前物品重量比列背包重量大, 则取上一行对应列的价格填入
v[i][j] = v[i - 1][j];
}else {
/*
当j>=w[i]时: v[i][j] = Math.max(v[i-1][j], val[i - 1] + v[i - 1][j - w[i -1]]);
代码解读:
当准备加入的新增的商品的容量小于等于当前背包的容量,装入的方式:
v[i-1][j]: 就是上一个单元格的装入的最大值
val[i - 1]] : 表示当前商品的价值
v[i-1][j-w[i]] : 装入i-1商品,到剩余空间j-w[i]的最大值
*/
//v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i -1]]); 以下是改良版
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[i][j] = 1;
}else {
v[i][j] = v[i - 1][j];
}
}
}
}
// 遍历输出展示
for (int i = 0; i < v.length; i++) {
for (int j = 0; j < v[0].length; j++) {
System.out.print(v[i][j] + "\t");
}
System.out.println();
}
System.out.println("========================");
/*
// 输出最后我们是放入的哪些商品
// 遍历path, 这样输出会把所有的放入情况都得到, 其实我们只需要最后的放入
for(int i = 0; i < path.length; i++) {
for(int j=0; j < path[i].length; j++) {
if(path[i][j] == 1) {
System.out.printf("第%d个商品放入到背包\n", i);
}
}
}*/
//优化
int i = path.length - 1; //行的最大下标
int j = path[0].length - 1; //列的最大下标
while(i > 0 && j > 0 ) { //从path的最后开始找
if(path[i][j] == 1) {
System.out.printf("第%d个商品放入到背包\n", i);
j -= w[i-1]; // 只需要移动到剩余背包空间对应的物品的值
}
i--;
}
}
}