题目
给定n种物品和一个背包,物品i的重量是wi,价值为vi,背包的容量为c。问如何选择装入背包的物品才能使得装入背包中的物品总价值最大?在选择装入背包的物品的时候,对每种物品i只有两种选择,即装入背包或者不装入背包。不能同时将物品i装入背包多次,也不能只装入部分物品i。因此该问题称为0-1问题。
分析
该问题形式化的描述为,给定c>0,wi>0,vi>0,1<=i<=n,要求找出一个n元0-1向量
(x1,x2,…,xn),xi∈(0,1),i<=i<=n,使得物品在不超过c的时候总价值最大。
其递推公式可以写为f[i][v]=max{ f[i-1][v], f[i-1][v-w[i]]+v[i] }。
具体问题
有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
根据题目递推公式 填表如下
name | weight | value | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
a | 2 | 6 | 0 | 3 | 3 | 6 | 6 | 9 | 9 | 15 | 15 | 15 |
b | 2 | 3 | 0 | 3 | 3 | 6 | 6 | 9 | 9 | 9 | 10 | 11 |
c | 6 | 5 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 10 | 11 |
d | 5 | 4 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 10 | 10 |
e | 4 | 6 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
程序
package cn.doodlister;
public class Kanpsack {
int v[],w[],c,n,m[][];//价格数组,重量数组,背包容量,物品个数,最优解
public Kanpsack(int v[],int w[],int c,int n,int m[][]){
this.v=v;
this.w=w;
this.c=c;
this.n=n;
this.m=m;
}
public void gen(){
int jMax=min(w[n]-1,c);//比较 第n个物品的重量和背包容量c的大小 取最小值
for(int i=0;i<=jMax;++i){//把m(n,j) 中j<c的时候 都赋值为0
m[n][i]=0;
}
for(int j=w[n];j<=c;++j){//把可以装下物品n的部分装下物品n
m[n][j]=v[n];
}
for(int i=n-1;i>1;--i){//继续计算接下来的行
jMax=min(w[i]-1,c);
for(int j=0;j<=jMax;++j){
m[i][j]=m[i+1][j];
}
for(int j=w[i];j<=c;++j){
m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
}
}
m[1][c]=m[2][c];
if(c>=w[1])
m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);
}
private int min(int a,int b){
return a<=b?a:b;
}
private int max(int a,int b){
return a>=b?a:b;
}
public void trackback(int x[]){//根据最优值表求最优解
for(int i=1;i<n;++i){
if(m[i][c]==m[i+1][c]){
x[i]=0;
}else {
c-=w[i];
x[i]=1;
}
}
x[n]=(m[n][c]!=0)?1:0;
}
}
package cn.doodlister;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int v[]={0,6,3,5,4,6};
int w[]={0,2,2,6,5,4};
int m[][]=new int[6][11];
int c=10,n=5;
int x[]=new int[6];
Kanpsack k=new Kanpsack(v,w,c,n,m);
k.gen();
k.trackback(x);
for(int i=0;i<=5;++i)
System.out.println(x[i]);
}
}
输出
0
1
1
0
0
1