问题描述:
有一个背包,容量为m,有n个物品,物品重量和价值自己输入,
要求背包装入的物品总价值最大。
import java.util.Scanner;
public class KnapsackProblem {
public static void main(String[] args) {
//给定n个物品,设v[i]、w[i]分别为第i个物品的价值和重量
//设v[i][j]表示在前i个物品中能够装入容量为j的背包中的最大价值
Scanner scanner = new Scanner(System.in);
System.out.println("请输入背包容量:");
int m = scanner.nextInt();
System.out.println("请输入物品个数:");
int n = scanner.nextInt();
int val[] = new int[n + 1];
int w[] = new int[n + 1];
//循环输入待放入背包的 物品的重量与价值
for(int i = 0; i < n;i++) {
System.out.println("请输入第" + (i + 1) + "个物品的重量:");
w[i] = scanner.nextInt();
System.out.println("请输入第" + (i + 1) + "个物品的价值:");
val[i] = scanner.nextInt();
}
//测试
// int v[][] = new int[n + 1][n + 1];
// int w[] = {1,4,3};//物品的重量
// int val[] = {1500,3000,2000};//物品的价值
// int m = 4;//背包的容量
// int n = val.length;//物品的个数
//创建二维数组
//v[i][j]表示在前i个物品中能够装入的容量为j的背包的最大价值
int v[][] = new int[n + 1][m + 1];
int path[][] = new int [n + 1][m + 1];
//初始化第一行第一列,全部为0(可以不处理,默认为0)
for(int i = 0;i < v.length;i++) {
v[i][0] = 0;
}
for(int i = 0;i < v[0].length;i++) {
v[0][i] = 0;
}
//动态规划处理
for(int i = 1;i < v.length;i++) {
for(int j = 1; j < v[0].length;j++) {
//如果当前物品重量大于当前背包的容量,表示装不下,继承上一个最大值
//由于w,val下标从0开始,这里小标从1开始,所以这里都要减1
if(w[i - 1] > j) {
v[i][j] = v[i - 1][j];
}else {
//如果当前物品的重量小于背包容量,为了装满,j - w[i - 1]表示剩余的容量,可通过v[i - 1][j - w[i - 1]]
//得出剩余容量可以装的最大值
//得到后还要与上一个最大值做比较,取最大的值
// v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i - 1]]);
if(v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
path[i][j] = 1;
}else {
v[i][j] = v[i - 1][j];
}
}
}
}
//测试输出
// for(int i = 0;i < v.length;i++) {
// for(int j = 0;j < v[i].length;j++) {
// System.out.print(v[i][j] + "\t");
// }
// System.out.println();
// }
int i = path.length - 1;//行最大下标
int j = path[0].length - 1;//列最大下标
while(i > 0 && j > 0) {
if(path[i][j] == 1) {
System.out.println("第" + i + "个物品装入背包");
j -= w[i - 1];//装入后减掉容量
}
i--;
}
}
}