什么是背包问题?
问题描述:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。即给定一个载重量为room的背包,另有num个物品,其每个物品重量为size_i,价值为value_i,1<=i<=n,选择物品装入背包,使得背包内的物品价值最大。
问题分析:
0-1背包问题可以看作是动态规划的一个经典案例。
在该问题中,物体只能选择装入背包或不装入背包。
我们借助一个辅助表table[num+1][room+1],table[i][j]表示前i个物品装入载重量为j的背包中的最大价值。
循环过程中,若size_i > j,表示当前物品重量超过当前背包载重量,则table[i][j]为不装入当前物品的价值,即table[i][j]=table[i-1][j];若size_i < j,表示当前物品重量小于当前背包的载重量,则table[i][j]为不装入当前物品和装入当前物品的价值的较大值,即table[i][j] = Max(table[i-1][j],table[i-1][j-size_i]+value_i)
测试:
输入背包容量:10
输入物品数量:5
输入物品重量和价值:1,1;3,2;2,4;4,5;6,2
填表结束后的辅助表如图:
下面给出背包问题的代码实现:
import java.util.Scanner;
/**
* 0-1背包问题
* @author zxy
*
*/
public class Bag {
private int room; //背包容量
private int num; //物品数量
private int[] size; // 物品重量表
private int[] value; //物品价值表
private int[][] table; //辅助表 竖轴num 横轴room 表中所填为当前背包容积的最大价值
public Bag(int room, int num) {
super();
this.room=room;
this.num = num;
this.size=new int[num+1];
this.value=new int[num+1];
this.table=new int[num+1][room+1];
}
/**
* 从左上角往右下角填0-1背包辅助表
* 表中右下角的值即为背包容量的最大价值
* @param bag
*/
public static void fun(Bag bag){
for(int i=1;i<=bag.num;i++){
for(int j=1;j<=bag.room;j++){
//背包容量小于当前物品重量,
//则当前背包容量最大价值为舍弃当前物品的价值
if(j<bag.size[i]){
bag.table[i][j]=bag.table[i-1][j];
//背包容量大于当前物品重量,
//则当前背包容量最大价值为舍弃当前物品和放入当前物品的价值的较大值
}else{
bag.table[i][j]=max(bag.table[i-1][j],bag.table[i-1][j-bag.size[i]]+bag.value[i]);
}
}
}
}
/**
* 获取较大值
* @param a
* @param b
* @return
*/
public static int max(int a, int b){
return a>b?a:b;
}
/**
* 打印0-1背包辅助表
* @param bag
*/
public static void out(Bag bag){
for(int i=0;i<=bag.num;i++){
for(int j=0;j<=bag.room;j++){
System.out.print(bag.table[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int room=scanner.nextInt();
int num=scanner.nextInt();
Bag bag=new Bag(room,num);
for(int i=1;i<=num;i++){
bag.size[i]=scanner.nextInt();
bag.value[i]=scanner.nextInt();
}
fun(bag);
out(bag);
}
}