题目:
给定n种物品和一背包。物品i的重量是wi,体积是bi,其价值为vi,背包的容量为C,容积为D。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或者不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。试设计一个解此问题的动态规划算法,并分析算法的计算复杂性。
题目分析:
说白了,学会只考虑重量和价值的动态规划解决0-1背包问题就会了这个问题,增加了一个条件所以二维变三维。
测试用例:
Input:
请输入物品个数:5
请输入背包容量:8
请输入背包容积:7
请分别输入物品重量:3 4 6 1 2
请分别输入物品体积:2 1 4 1 4
请分别输入物品价值:6 5 7 3 8
Output:
最大总价值是:17
被选入背包的物品的编号,质量和体积,价值分别是:
第1个物品:3 2 6
第4个物品:1 1 3
第5个物品:2 4 8
代码实现:
import java.util.Scanner;
public class Knapsack {
private static int n;//表示有多少个物品
private static int c;//容量
private static int d;//容积
private static int[] weightArr;
private static int[] volumeArr;
private static int[] valueArr;
private static int[][][] dp;
public static void main(String[] 施凡奕) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入物品个数:");
n = sc.nextInt();
System.out.print("请输入背包容量:");
c = sc.nextInt();
System.out.print("请输入背包容积:");
d = sc.nextInt();
weightArr = new int[n + 1];
volumeArr = new int[n + 1];
valueArr = new int[n + 1];
dp = new int[n + 1][c + 1][d + 1];//dp[i][j][k]i代表着第1到第i个物品,j代表的是重量,k代表的是容积,dp为最优价值
System.out.println("请分别输入物品重量:");
for (int i = 1; i <= n; i++) {
weightArr[i] = sc.nextInt();
}
System.out.println("请分别输入物品体积:");
for (int i = 1; i <= n; i++) {
volumeArr[i] = sc.nextInt();
}
System.out.println("请分别输入物品价值:");
for (int i = 1; i <= n; i++) {
valueArr[i] = sc.nextInt();
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= c; j++) {
for (int k = 1; k <= d; k++) {
if (j >= weightArr[i] && k >= volumeArr[i]) {
dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - weightArr[i]][k - volumeArr[i]] + valueArr[i]);
} else {
dp[i][j][k] = dp[i - 1][j][k];
}
}
}
}
System.out.println("最大总价值是:" + dp[n][c][d]);
int x[] = new int[99]; //记录是否被选中
for (int i = n; i > 1; i--)
if (dp[i][c][d] == dp[i - 1][c][d]) {
x[i] = 0;
} else {
x[i] = 1;
c -= weightArr[i];
d -= volumeArr[i];
}
x[1] = (dp[1][c][d] != 0) ? 1 : 0;
System.out.println("被选入背包的物品的编号,质量和体积,价值分别是:");
for (int i = 1; i < n + 1; i++)
if (x[i] == 1)
System.out.println("第" + i + "个物品:" + weightArr[i] + " " + volumeArr[i] + " " + valueArr[i]);
}
}
运行结果: