01背包
给定N个物品和容量为C的背包,每个物品的体积为w[i],每个物品的价值为v[i],问如何装入物品使背包中的总价值最大?
思路:
给定一个F[i][j]二维数组,代表前i个物品装入容量为j的背包中的价值最大。
主要考虑第i件物品背包是否可以装的下。如果装的下,应该考虑装下的价值和不装的价值哪个大,则F[i][j] =max{ F[i - 1][j - w[i]] + v[i],F[i - 1][j] };如果装不下,则F[i][j] = F[i - 1][j] ;
建立的数组为F[i][j],大小为(N+1,C+1),这是需要考虑到什么都不装的时候价值为0;
w[i],大小为(0,N - 1);v[i],大小为(0,N - 1);
import java.util.Scanner;
public class pack01 {
private int N;
private int C;
private int[] w; //体积
private int[] v; //价值
private int[][] F; //总价值
private boolean[][] flag; //指示哪些装入背包
public void init() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入物品数量:");
N = sc.nextInt();
System.out.println("请输入背包大小:");
C = sc.nextInt();
w = new int[N];
v = new int[N];
System.out.println("请输入各物品大小:");
for (int i = 0; i < N; i++) {
w[i] = sc.nextInt();
}
System.out.println("请输入各物品价值:");
for (int i = 0; i < N; i++) {
v[i] = sc.nextInt();
}
F = new int[N + 1][C + 1];
flag = new boolean[N + 1][C + 1];
for (int i = 0; i < F.length; i++) {
F[i][0] = 0;
flag[i][0] = false;
}
for (int i = 0; i < F[0].length; i++) {
F[0][i] = 0;
flag[0][i] = false;
}
}
public void solution() {
for(int i = 1; i <= N; i ++) {
for (int j = 0; j <= C; j++) {
if(j > w[i - 1]) { //可以装的下
if(F[i - 1][j - w[i - 1]] + v[i - 1] > F[i - 1][j]) { //不添加装入背包的内容就用下面一句max()
F[i][j] = F[i - 1][j - w[i - 1]] + v[i - 1];
flag[i][j] = true;
}else {
F[i][j] = F[i - 1][j];
}
//F[i][j] = Math.max(F[i - 1][j - w[i - 1]] + v[i - 1], F[i - 1][j]);
}else {
F[i][j] = F[i - 1][j];
}
}
}
//输出结果
for(int i = 0; i <= N; i ++) {
for (int j = 0; j <= C; j++) {
System.out.print(F[i][j] + " ");
}
System.out.println();
}
int i = flag.length - 1;
int j = flag[0].length - 1;
while(i > 0 && j > 0) {
if(flag[i][j] == true) {
System.out.print("第" + i + "个物品装入");
j = j - w[i - 1];
}
i --;
}
}
public static void main(String[] args) {
pack01 instance = new pack01();
instance.init();
instance.solution();
}
}