package com.xiejianjun.day12;
import java.util.Arrays;
/**
* @author bilibilidick
* @version 2022 04
* @date 2022/4/28 15:36
*/
public class _01Backpack {
//物品质量
private final int[] w = {1, 4, 3};
//物品价值
private final int[] v = {1500, 3000, 2000};
//背包容量
private final int backpackV = 4 ;
//总价值二维数组
private int[][] dp;
public void displayDpArr() {
if (dp == null) return;
for (int[] ints : dp) {
System.out.println(Arrays.toString(ints));
}
int i = dp.length - 1;
int j = dp[0].length - 1;
while (i > 0) {
// if (result[i][j] == 1) {
// 如果上一行的价值与本行价值不同,可说明此物品已经被放入背包中
// 输出本物品已放入背包的消息,并且移动与本物品相同重量的列数,意义为去掉背包中此物品的重量
if (dp[i][j] != dp[i - 1][j]) {
System.out.println("序号" + i + "的物品已放入背包中");
j -= w[i - 1];
}
else {
System.out.println("序号" + i + "的物品未放入背包中");
}
// 每次检查背包物品,都需要往上走一行,意义为去掉背包中此物品
i--;
}
}
public void getDp() {
init();
// 从i=1开始是因为i=0已经被初始化过了,即第一行全是0,代表前零个物品放入容量为i的背包所拥有的价值
for (int i = 1; i <= w.length; i++) {
// 外部循环从背包容量为0起始,直到达到最大背包容量位置
for (int j = 0; j <= backpackV; j++) {
// 记得i要减1,因为本程序数组是从0开始放物品价值的,在第56行的v数组的i值同理
// 如果发现本物品重量大于背包容量,则不放入
if (w[i - 1] > j) {
dp[i][j] = dp[i - 1][j];
} else {
// 如果发现本物品重量小于背包容量
// 则将背包的容量扣掉本物品的重量后,再与背包剩余的容量所能达到的最优价值加上本物品的价值
// 与不放入本物品的背包总价值相比较
// 取最大值放入DP数组
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
}
}
}
/*
初始化数组,因需要考虑临界值,数组长度与宽度应比背包容量与物品数量多一
[0, 0, 0, 0, 0]
[0, 1500, 1500, 1500, 1500]
[0, 1500, 1500, 1500, 3000]
[0, 1500, 1500, 2000, 3500]
*/
}
private void init() {
/*
初始化数组,因需要考虑临界值,数组长度与宽度应比背包容量与物品数量多一
其实不刻意写也是零
因为jvm在类装载的第二个阶段链接阶段,此阶段中的第二步准备中会将数组的值赋予零值
也能达到同样的效果
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
*/
this.dp = new int[w.length + 1][backpackV + 1];
for (int i = 0; i < w.length + 1; i++) {
for (int j = 0; j < backpackV + 1; j++) {
dp[i][j] = 0;
}
}
}
public static void main(String[] args) {
_01Backpack backpack = new _01Backpack();
backpack.getDp();
backpack.displayDpArr();
}
}