Java 多功能背包
给定问题: n个项目,每个项目都有一个Java 多功能背包,java,algorithm,dynamic-programming,knapsack-problem,Java,Algorithm,Dynamic Programming,Knapsack Problem,给定问题: n个项目,每个项目都有一个值val、一个重量w、一个体积vol。基本上与背包0/1问题相同,但任务是找到背包中的最大值V,但重量不能超过W_max,体积至少需要Vol_min 值、重量和体积以三个数组表示: val[n+1], w[n+1], vol[n+1] The i-th item has value val[i], weight w[i] and volume vol[i] 我知道如何解决只有一个极限的正常0/1背包问题,但我不知道如何解决这个问题。我曾考虑使用3D DP表
值val
、一个重量w
、一个体积vol
。基本上与背包0/1问题相同,但任务是找到背包中的最大值V,但重量不能超过W_max,体积至少需要Vol_min
值、重量和体积以三个数组表示:
val[n+1], w[n+1], vol[n+1]
The i-th item has value val[i], weight w[i] and volume vol[i]
我知道如何解决只有一个极限的正常0/1背包问题,但我不知道如何解决这个问题。我曾考虑使用3D DP表,但表中的条目是如何定义的
以下是我迄今为止所尝试的:
static int knapsack(int[] vol, int[] w, int[] val, int n, int Vol_min, int W_max) {
int[][][] DP = new int[n+1][W_max][Vol_min];
for(int i = 1; i < n+1; i++) {
for(int j = 0; j < W_max; j++) {
for(int k = 0; k < Vol_min; k++) {
if(w[i] > W_max) {
DP[i][j][k] = DP[i-1][j][k];
} else {
if(j - w[i] >= 0 && k + vol[i] <= n) {
DP[i][j][k] = Math.max(DP[i-1][j][k], DP[i-1][j - w[i]][k + vol[i]] + val[i]);
} else {
DP[i][j][k] = DP[i-1][j][k];
}
}
}
}
}
return DP[n][n][n];
}
因此,使用递归DP,我对1/0背包提出了一个非常标准的解决方案,只做了一点修改
public static int[][] dp;// Item number, Weight, Volume
public static int[] vol, w, val;
public static int Vol_min, W_max, n;
static int knapsack(int item, int weight, int volume) {
// See if we have calculated this item before
if (dp[item][weight] == -1) {
// Set initial value to -2 (invalid result)
int max = -2;
// Iterate though all items past current item
for (int i = item; i < n; i++) {
// Make sure we don't go over max weight
if (weight + w[i] <= W_max) {
// Get the result of taking ith item
int res = knapsack(i + 1, weight + w[i], volume + vol[i]);
// Make sure result is valid (Total volume is greater than
// Vol_min)
if (res != -2) {
// If the result is valid take the max
max = Math.max(res + val[i], max);
}
}
}
if (max == -2 && volume >= Vol_min)// No other items taken and over
// Vol_min
dp[item][weight] = 0;
else // Eveything else
dp[item][weight] = max;
}
// Return the value
return dp[item][weight];
}
public static void main(String[] args) {
n = 6;
Vol_min = 10;
W_max = 12;
vol = new int[] { 1, 3, 7, 5, 1, 3 };
w = new int[] { 4, 5, 10, 2, 1, 4 };
val = new int[] { 10, 8, 5, 3, 1, 2 };
dp = new int[n + 1][W_max + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= W_max; j++) {
dp[i][j] = -1;
}
}
System.out.println(knapsack(0, 0, 0));
}
publicstaticint[]dp;//项目编号、重量、体积
公共静态int[]卷,w,val;
公共静态整数最小值,最大值,n;
静态整数背包(整数项、整数重量、整数体积){
//看看我们以前是否计算过这个项目
如果(dp[项目][重量]=-1){
//将初始值设置为-2(结果无效)
int max=-2;
//迭代当前项之前的所有项
对于(int i=项;i 对于(int i=0;idp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-w[i]][k-vol[i]]+val[i])
-???@ShihabShahriar我认为如果最大卷是一个上限,那么这将是一个解决方案,但这里的卷是最小的,即下限。你应该能够让第三维表示给定卷的最大值,而不是现在所有卷的最大值。这是一个竞争问题吗分享到问题的链接?我很确定这是可以做到的,但是如果有一个地方可以让我得到判断结果,我可以更具体一点。@kevmo314我添加了一个简单的例子,不幸的是,我不能给你到判断的链接,因为它对某些用户是有限的…@G.m你考虑过使用递归DP吗?
public static int[][] dp;// Item number, Weight, Volume
public static int[] vol, w, val;
public static int Vol_min, W_max, n;
static int knapsack(int item, int weight, int volume) {
// See if we have calculated this item before
if (dp[item][weight] == -1) {
// Set initial value to -2 (invalid result)
int max = -2;
// Iterate though all items past current item
for (int i = item; i < n; i++) {
// Make sure we don't go over max weight
if (weight + w[i] <= W_max) {
// Get the result of taking ith item
int res = knapsack(i + 1, weight + w[i], volume + vol[i]);
// Make sure result is valid (Total volume is greater than
// Vol_min)
if (res != -2) {
// If the result is valid take the max
max = Math.max(res + val[i], max);
}
}
}
if (max == -2 && volume >= Vol_min)// No other items taken and over
// Vol_min
dp[item][weight] = 0;
else // Eveything else
dp[item][weight] = max;
}
// Return the value
return dp[item][weight];
}
public static void main(String[] args) {
n = 6;
Vol_min = 10;
W_max = 12;
vol = new int[] { 1, 3, 7, 5, 1, 3 };
w = new int[] { 4, 5, 10, 2, 1, 4 };
val = new int[] { 10, 8, 5, 3, 1, 2 };
dp = new int[n + 1][W_max + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= W_max; j++) {
dp[i][j] = -1;
}
}
System.out.println(knapsack(0, 0, 0));
}