import java.util.Arrays;
/**
* 0-1背包问题:算例
* 背包容量=10,5个可选物品
* 相应重量{2,4,6,5,2}
* 相应价值{3,5,6,7,4}
* 求背包最多可装多少价值物品
* 思路:动态规划
* 算法:当j<wi时,v(i,j)=v(i-1,j)
* 当j>=wi时,v(i,j)=max{v(i-1,j),v(i-1,j-wi)+vi}
*
* 求最大价值时,背包中物品有哪些
* 思路:回溯
* 算法:当v(i,j)=v(i-1,j)时,xi=0
* 当v(i,j)>v(i-1,j)时,xi=1,j=j-wi
*
* @author Chill Lyn
*
*/
public class _01Knapsack {
public static void main(String[] args) {
int num=5; //物品数量
//对应各物品重量,0为边界值,可以理解为第0个物品重量为0
//最好设置两个相同重量不同价值的物品,加深理解;
int[] weight= {0,2,4,6,5,2};
//对应各物品价值,0为边界值,可以理解为第0个物品价值为0
int[] value= {0,3,5,6,7,4};
int capacity=10;//背包容量
//声明动态规划表v[i][j],当 前i个物品可选,背包容量为j时,价值最大值
int[][] v=new int[num+1][capacity+1];
for(int i=0;i<=num;i++) {
for(int j=0;j<=capacity;j++) {
if(i==0||j==0) {
v[i][j]=0;//边界值,可理解为0个物品可选,或背包容量为0时
}else {
//背包容量j小于物品i重量,保持上次最大值
if(j<weight[i]) {
v[i][j]=v[i-1][j];
//背包可装,装与不装选最优
}else {
v[i][j]=Math.max(v[i-1][j], v[i-1][j-weight[i]]+value[i]);
}
}
}
}
System.out.println("动态规划表:");
for(int i=0;i<=num;i++) {
for(int j=0;j<=capacity;j++) {
System.out.print(v[i][j]+"\t");
}
System.out.println();
}
System.out.println("背包里物品最大价值总和:"+v[num][capacity]);
//背包里价值最大时,装了哪些物品,回溯
//创建一个大小为[num+1]全元素为0的数组,备用标记
int[] chosen =new int[num+1];
Arrays.fill(chosen, 0);
int j=capacity;
for(int i=num;i>0;i--) {
if(v[i][j]>v[i-1][j]) {
chosen[i]=1;
j=j-weight[i];
}
}
System.out.print("背包中物品编号:");
for(int i=0;i<=num;i++) {
if(chosen[i]==1) {
System.out.print(i+" ");
}
}
}
}
初始条件
结果:
回溯所选物品