问题描述:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装
入背包中物品的总价值最大?
对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态可以取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。
`
public class PacketQuestion {
public static void main(String[] args) {
int c = 10;//背包的总容量
int[] w = {0,2,2,6,5,4};//每个物体的重量
int[] v = {0,6,3,5,4,6};//每个物理的价值
int n = w.length;//计算物体的个数
int x[] = new int[n];//x[i]的值要么为0要么为1,1表示放当前i的物品,0表示不放当前i的物品
int[][] m = new int[n][11];//存放可能性的二维数组
packet0_1(m,w,v,c);//该方法就是构造最优解的那个二维数组m
//输出构造的二维数组的结果
for (int i = 1; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
System.out.print(m[i][j] + " ");
}
System.out.println();
}
/*
*输出结果为:
0 0 6 6 9 9 12 12 15 15 15
0 0 3 3 6 6 9 9 9 10 11
0 0 0 0 6 6 6 6 6 10 11
0 0 0 0 6 6 6 6 6 10 10
0 0 0 0 6 6 6 6 6 6 6
*/
//根据构造的二维数组,给x赋值
answer(m,w,c,x);
System.out.print("是否装物品的数组:");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
/*
结果为:是否装物品的数组(x数组的值为):0 1 1 0 0 1
*/
//总价值
int value = getValues(v,x);
System.out.print("最高总价值 : ");
System.out.println(value);
/*
* 总价值 : 15
*/
}
private static int getValues(int[] v, int[] x) {
int value = 0;//最初的价值为0
for (int i = 0; i < x.length; i++) {
value += v[i] * x[i];//当前物品的价值 * 该物体是否被放。
}
return value;
}
//根据最优解的结果为x数组赋值,顺序是从上到下,从左到右。x数组的值有两个,1表示选该物体,0表示不选该物体
private static void answer(int[][] m,int[] w, int c, int[] x) {
int j = c;//最初的总重量
int i = 1;
int n = w.length;
//遍历每一行的值
for (i = 1; i < n-1; i++) {
//如果承重为j的包所放当前物体最大价值等于下一个物体的最大价值,说明该物体没有被放进包里,所以x[i] = 0
if (m[i][j] == m[i+1][j]) {
x[i] = 0;
}else{//反之,放入包里了,x[i]置1,包的空间数减去当前物体的重量
x[i] = 1;
j = j - w[i];//放该物体后,剩余的空间
}
}
x[n-1] = m[i][j] != 0 ? 1 : 0; //承重为j的包所放当最后一个物体的价值不为0,说明放了最后一个物体,反之没有放。
}
private static void packet0_1(int[][] m, int[] w, int[] v, int c) {
int n = m.length;
//给二维数组的最后一行赋值
//因为最后一行只存放最后一个物体,所以背包承重大于物体重量,就放该物体,二维数组的就就是物体的价值,否则就不放该物体
for (int i = 0; i <= c; i++) {
//放该物体
if (i >= w[n-1]) {
m[n-1][i] = v[n-1];
}else{//不放该物体
m[n-1][i] = 0;
}
}
//从倒数第二行开始向前为每个二维数组对应的值赋值
for (int i = n - 2; i > 0; i--) {//控制行值
for (int j = 0; j <= c; j++) {//控制列值,也就是当前包的承重
if (j < w[i]) {
//如果当前背包的承重小于当前物体的重量,那么当前背包的承重就等于下一个位置的值
m[i][j] = m[i+1][j];
}else{
//否则就比较该位置放该物体,与不放该物体的价值哪个大,哪个大就放哪个
/*
* m[i+1][j - w[i]] + v[i]:
* v[i]是当前物体的价值
* m[i+1][j - w[i]]是除去当前物体的重量后背包能放的最大重量,第j-w[i]的背包能放的最大价值就是i+1列
* m[i+1][j]:表示不放该物体时背包能放的最大价值
*/
m[i][j] = Math.max(m[i+1][j - w[i]] + v[i], m[i+1][j]);
}
}
}
}
}
`