给定种物品和一个背包。物品
的重量是
,其价值为
,背包的容量为
。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大? (
,
和
都是整数)
定义子问题
将物品用 1,2,... ,n编号, 子问题可以定义为 = {在1, 2, ... , k号物品中找最优解}
问题是: 我们能否将问题( )的最优解 用子问题 (
)的最优解表示?
定义新的子问题
1.增加一个参数 w : 中的物品的重量
2.定义 B[w][k] =放入背包中的编号不超过k、重量不超过w的物品的总价值.
附java代码
package package0_1;
/**
* 0-1背包问题
* @author Dudu
* @date 2018-11-11
*/
public class Knapsack0_1Algorithm {
public static void marknumber(int n,int W,int[][] B ,int[] b,int v)
{
//给选择到的物品打标号1 表示选择 ,0表示不选
int[] x = new int[n];
while (v > 0) {
flag:for (int i = 1;i <= n;i++) {
for (int w = 1;w <= W;w++) {
if (B[w][i] == v) {
//按列选择第一个达到最优值的位置得到第一个编号,减去当前编号的价值,得到上一个物品的价值,再去搜索上一个物品的编号
x[i-1] = 1;
v = v - b[i-1];
break flag;
}
}
}
}
System.out.print("选择装入背包的物品编号为:"); //从1开始编号
for (int j = 0;j < n;j++) {
if (x[j] == 1) {
System.out.print(j+1+" ");
}
}
System.out.println();
}
public static int knapsack0_1(int n,int[] b,int[] wlist,int W) {
/**
* n: 物体总数
* b: 价值数组 存放每个物品的价值
* wlist: 重量数组 存放每个物品的重量
* W: 背包所能够承载的总重量
*/
int[][] B = new int[W+1][n+1];
for (int w = 0;w <=W;w++) {
B[w][0] = 0;
}
for (int i = 1;i <= n;i++) {
B[0][i] = 0;
for (int w = 1;w <= W;w++) {
try {
if (wlist[i-1] <= w) {
B[w][i] = Math.max(b[i-1] + B[w-wlist[i-1]][i-1], B[w][i-1]);
// if (b[i-1] + B[w-wlist[i-1]][i-1] > B[w][i-1])
// {
// B[w][i] = b[i-1] + B[w - wlist[i-1]][i-1];
// }
// else {
// B[w][i] = B[w][i-1];
// }
}
else
{
B[w][i] = B[w][i-1];
}
}catch(IndexOutOfBoundsException e){
System.out.println("IndexOutOfBoundsException");
continue;
}
}
}
System.out.println("输出B矩阵如下:行代表W,列代表物品编号n");
for (int w = 0;w <= W;w++) {
for (int i = 0;i <= n;i++) {
System.out.print(B[w][i]+"\t");
}
System.out.println();
}
marknumber(n,W,B,b,B[W][n]);
return B[W][n];
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] w = {2,3,4,5,9};
int[] b = {3,4,5,8,10};
int n = w.length;
int W = 20;
int value = knapsack0_1(n,b,w,W);
System.out.println("价值为:"+value);
}
}
输出结果
输出B矩阵如下:行代表W,列代表物品编号n
0 0 0 0 0 0
0 0 0 0 0 0
0 3 3 3 3 3
0 3 4 4 4 4
0 3 4 5 5 5
0 3 7 7 8 8
0 3 7 8 8 8
0 3 7 9 11 11
0 3 7 9 12 12
0 3 7 12 13 13
0 3 7 12 15 15
0 3 7 12 16 16
0 3 7 12 17 17
0 3 7 12 17 17
0 3 7 12 20 20
0 3 7 12 20 20
0 3 7 12 20 21
0 3 7 12 20 22
0 3 7 12 20 23
0 3 7 12 20 25
0 3 7 12 20 26
选择装入背包的物品编号为:1 3 4 5
价值为:26