1、基本介绍
2、应用实践(01背包问题)
package algorithm;
import java.util.Arrays;
public class KnapSackProblem {
public static void main(String[] args) {
int[] weight = {1,4,3}; // 物品的重量
int[] price = {1500,3000,2000}; // 物品的价格
int count = weight.length; // 物品数量
int sack = 4; // 背包容量
knapSack(weight, price, count, sack);
}
private static void knapSack(int[] weight, int[] price, int count, int sack) {
int[][] path = new int[count + 1][sack + 1]; // 记录放入的物品
int[][] v = new int[count + 1][sack + 1]; // 代表的是总价值
// 初始化一下v数组,确保物品跟磅数相对应(最起码得从1磅开始)
for (int i = 0; i < v.length; i++) {
v[i][0] = 0;
}
for (int j = 0; j < v[0].length; j++) {
v[0][j] = 0;
}
System.out.println("原最大价值数组:");
print(v);
for (int i = 1; i < v.length; i++) { // 下标从1开始
for (int j = 1; j < v[0].length; j++) { // 下标从1开始
if (weight[i - 1] > j) { // 如果当前物品的重量大于当前背包的容量(物品的下标是从0开始的,所以需要-1)
v[i][j] = v[i - 1][j]; // 用上一个单元的值填充该单元
} else { // 如果当前物品的重量 <= 当前背包的容量(将放入该物品和不放入比较)
if (v[i-1][j] > price[i - 1] + v[i - 1][j - weight[i - 1]]) {
v[i][j] = v[i-1][j];
} else {
v[i][j] = price[i - 1] + v[i - 1][j - weight[i - 1]];
path[i][j] = 1; // 记录的是每一次新放入的物品(而不是由上一个单元填充的值)
}
}
}
}
System.out.println("放物品后的最大价值数组:");
print(v); // 标记为1的都为放入的物品
System.out.println("放入过的物品");
print(path);
// 统计最后放入的物品(从后往前统计),即实现背包的最大价值
int i = path.length - 1;
int j = path[i].length - 1;
while(i > 0 && j > 0) {
if (path[i][j] == 1) { // 表明是放入的物品
System.out.println("第" + i + "个商品放入背包!");
j -= weight[i - 1]; // 取出物品后,减去对应的重量
}
i--;
}
}
public static void print(int[][] arr) {
for (int[] temp : arr) {
System.out.println(Arrays.toString(temp));
}
System.out.println();
}
}