题目描述
给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,背包的容量为C。如何选择装入背包的物品,可以使得装入背包中物品的总价值最大?
输入
每组输入包括三行,
第一行包括物品个数n,以及背包容量C。
第二、三行包括两个一维数组,分别为每一种物品的价值和重量。
输出
输出包括两行,第一行为背包的最大总价值,第二行为所选取的物品。
例如:最大总价值=15,物品选取策略为11001。
样例输入 Copy
5 10
6 3 5 4 6
2 2 6 5 4
样例输出 Copy
15
11001
具体的注意事项注释有
import java.util.Scanner;
public class Zero_OneBag {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();//物品的个数
int w=sc.nextInt();//背包的容量
int array_v[]=new int[n+1];//价值数组
int array_w[]=new int[n+1];//重量数组
int x[]=new int[n+1];//记录数组
int m[][]=new int[n+1][w+1];//记录数组
for(int i=1;i<=n;i++) {
array_v[i]=sc.nextInt();//从1开始记录
}
for(int i=1;i<=n;i++) {
array_w[i]=sc.nextInt();//从1开始记录
}
int res=zero_onebag(array_v,array_w,w,m);
System.out.println(res);
traceback(m,array_w,w,x);
for(int i=1;i<=n;i++) {
System.out.print(x[i]);
}
}
private static int zero_onebag(int[] array_v, int[] array_w, int w, int[][] m) {
int n=array_v.length-1;
int max=Math.min(array_w[n]-1, w);
/*
* 最后一行单独处理
*/
for(int i=0;i<=max;i++) {
m[n][i]=0;
}
for(int i=array_w[n];i<=w;i++) {
m[n][i]=array_v[n];
//第n行不需要考虑放不放,只要放的下肯定要放,有总比没有好
}
/*
* 1到n-1处理
*/
for(int i=n-1;i>=1;i--) {
max=Math.min(array_w[i]-1, w);
for(int j=0;j<=max;j++) {
m[i][j]=m[i+1][j];
}
for(int j=array_w[i];j<=w;j++) {
m[i][j]=Math.max(m[i+1][j], m[i+1][j-array_w[i]]+array_v[i]);
/*
* 就是来判断第n-1个物品值不值得放,如果放上以后,价值是 m[i+1][j-array_w[i]]+array_v[i];
* 但是有可能 m[i+1][j-array_w[i]]=0,因为可能容量不够,放不下第n个
*/
}
}
return m[1][w];
}
public static void traceback(int m[][],int array_w[],int w,int x[]) {
/*
* 构造路径,首先比较m[i][w]和m[i+1][w];
* 如果相同说明没放第i个,如果不同则说明放了
* 再将w减去放了的重量
*/
int n=array_w.length-1;
for(int i=1;i<n;i++) {
if(m[i][w]==m[i+1][w]) {
x[i]=0;
}
else {
x[i]=1;
w-=array_w[i];
}
x[n]=(m[n][w]>0)?1:0;
}
}
}