基本的0-1背包问题。这里的物品一般指花瓶、玉器什么的,要么拿,要么不拿,只有0和1两种状态,所以也叫0-1背包。
初学者有时会认为,0-1背包可以这样求解:计算每个物品的,然后依据
的值,对所有的物品从大到小进行排序。其实这种贪心方法是错误的。如下表,有三件物品,背包的最大负重量是50,求可以取得的最大价值。
其实,0-1背包是DP的一个经典实例,可以用动态规划求解。
0-1背包问题:
有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
转移方程如图所示。
解释一下上面的方程:将前i件物品放入容量为j的背包中这个问题时,如果只考虑第i件物品放或者不放,那么就可以转化为只涉及前i-1件物品的问题。
1)如果不放第i件物品,则问题转化为前i-1件物品放入容量为j的背包中。
2)如果,即背包剩余容量可以容纳第i件物品,那么放第i件物品,则问题转化为前i-1件物品放入剩下的容量为
的背包中,此时能获得的最大价值就是
再加上通过放入第i件物品获得的价值
。则
的值就是1)、2)中最大的那个值。
代码如下
public class Demo1 {
//总的重量
int totalWeight ;
//物品个数
int number ;
public Demo1(int number,int totalWeight){
this.totalWeight = totalWeight ;
this.number = number ;
}
public int knapsack(int w[],int v[]){
int m[][] = new int[number+1][totalWeight+1] ;
for(int j=0;j<totalWeight+1 ;j++){
m[0][j] = 0 ;
}
for(int i=0;i<number+1;i++){
m[i][0] = 0 ;
}
for(int i=1;i<number+1;i++){
for(int j=1;j<totalWeight+1;j++){
if(j>=w[i-1]){
m[i][j] = Math.max(m[i-1][j],m[i-1][j-w[i-1]]+v[i-1]) ;
}else{
m[i][j] = m[i-1][j] ;
}
}
}
for(int i=0;i<number+1;i++){
for(int j=0;j<totalWeight+1;j++){
System.out.print(m[i][j]+ " " );
}
System.out.println();
}
return m[number][totalWeight] ;
}
public static void main(String args[]){
//重量
int w[] = {3,4,5} ;
//价值
int v[] = {4,5,6} ;
Demo1 demo = new Demo1(3,10) ;
int weight = demo.knapsack(w,v) ;
System.out.println(weight);
}
}
背包容量的增长如图所示