问题描述
某商店有n个重量为Wi的物品,价值为Vi,小偷的背包最大可容纳重为M的物品,问小偷应该偷那些物品能够使得偷的的东西价值最高。
因为对于每个物品只有选和不选两种情况,所以这个问题称为0-1背包问题
例题:
商店有商品如下表,小偷的背包可装的重量为20
先来看一下公式
例如B(1,2)表示在0号和1号商品中选择,此时背包容量为2,能获得的最大价值
本题要求的则是B(4,20),过程如下
此过程可用二维数组实现:
定义一个数组res[6][21]
初始化res[i][0] = 0 res[0][i] = 0
然后双重循环:根据公式给数组中每一个元素赋值(每一个元素的值的计算依赖前面算过的值)
for (int i = 1; i < res.length; i++) {
for (int j = 1; j < res[0].length; j++) {
if(weight[i - 1] > j) {
res[i][j] = res[i - 1][j];
}else {
res[i][j] = max(res[i - 1][j - weight[i - 1]] + value[i - 1], res[i - 1][j]);
}
}
}
具体代码如下
代码
public class _01Bag {
public static void main(String[] args) {
int[] weight = {2,3,4,5,9};
int[] value = {3,4,5,8,10};
int bag = 20;
solution(weight, value, bag);
}
private static void solution(int[] weight, int[] value, int bag) {
int[][] res = new int [weight.length + 1][bag + 1];
//初始化dp矩阵
for (int i = 0; i < res[0].length; i++) {
res[0][i] = 0;
if(i < res.length)
res[i][0] = 0;
}
for (int i = 1; i < res.length; i++) {
for (int j = 1; j < res[0].length; j++) {
if(weight[i - 1] > j) {
res[i][j] = res[i - 1][j];
}else {
res[i][j] = max(res[i - 1][j - weight[i - 1]] + value[i - 1], res[i - 1][j]);
}
}
}
for (int i = 0; i < res.length; i++) {
System.out.println();
for (int j = 0; j < res[0].length; j++) {
System.out.print(res[i][j] + " ");
}
}
}
private static int max(int i, int j) {
if(i > j)
return i;
else
return j;
}
}