问题求解思路
1.将原问题分解为多个子问题
定义一个二维数组,其中每个元素代表前个物体中若干个放入体积为背包中最大价值。其中表示前件中若干个物品放入体积为的背包中的最大价值。
2.确定初始状态
初始状态都为0,前者表示前0个物品(也就是空物品)无论装入多大的包中总价值都为0,后者表示体积为0的背包啥价值的物品都装不进去。
3.确定状态转移方程
if(背包体积j < 物品体积i){
背包装不下第i个物体,只能装第i-1个物体
}else{
装入第i个物体
}
代码展示
package project;
public class beibao01 {
public static void main(String[] args) {
int[] w = {3, 2, 2};
int[] v = {5, 10, 20};
knapsackOptimal(5, w, v);
}
/**
* 01背包-容量压缩
*
* @param c 包容量
* @param weight 各物品质量
* @param value 各物品价值
*/
public static void knapsackOptimal(int c, int[] weight, int[] value) {
int n = weight.length; //物品数量
int[] w = new int[n + 1];
int[] v = new int[n + 1];
int[][] G = new int[n + 1][c + 1];
for (int i = 1; i < n + 1; i++) {
w[i] = weight[i - 1];
v[i] = value[i - 1];
}
int[] values = new int[c + 1];
for (int i = 1; i < n + 1; i++) {
for (int t = c; t >= w[i]; t--) {
if (values[t] < values[t - w[i]] + v[i]) {
values[t] = values[t - w[i]] + v[i];
G[i][t] = 1;
}
}
}
System.out.println("最大价值为: " + values[c]);
System.out.print("装入背包的物品编号为: ");
int i = n;
int j = c;
while (i > 0) {
if (G[i][j] == 1) {
System.out.print(i + " ");
j -= w[i];
}
i--;
}
}
}