经典动态规划:0-1 背包问题 :: labuladong的算法小抄 #1078
Replies: 20 comments 11 replies
-
能给出leetcode题号,实操一下吗 |
Beta Was this translation helpful? Give feedback.
-
这篇文章力扣没有对应题目 |
Beta Was this translation helpful? Give feedback.
-
而 dp[i-1][w - wt[i-1]] 也很好理解:你如果装了第 i 个物品,就要寻求剩余重量 w - wt[i-1] 限制下的最大价值,加上第 i 个物品的价值 val[i-1]。 --amazing。如果背包载重为5,前面已经装过数种方案。。假如这时要装的物品重量为2,那么之前的方案只能选重量为3时的最大化方案【不要考虑没有物品重量加起来是否刚好可以等于3,因为在w为3的情况下,也已经过了一遍最大化方案,假如只有重量为2的物品,那么重量相加不可能等于3,3的场景最大化收益就等于2的最大化收益【2 + 2 装不进背包,只能丢掉,只能取2的最大化收益】】。 |
Beta Was this translation helpful? Give feedback.
-
为什么把n放在外层循环把w放在内层循环?怎么判断状态的顺序? |
Beta Was this translation helpful? Give feedback.
-
遍历范围如果精确一下的话,似乎就不需要额外判断装不下的情况(索引溢出) for (int w = wt[i]; w <= W; w++) |
Beta Was this translation helpful? Give feedback.
-
这两个都是 0-1 背包的题呀 |
Beta Was this translation helpful? Give feedback.
-
@DapengJin 这两个是背包问题,但不是 0-1 背包,我都有写过的 |
Beta Was this translation helpful? Give feedback.
-
题目中的: 其中第 i 个物品的重量为 wt[i],价值为 val[i] 是不是有点矛盾啊? |
Beta Was this translation helpful? Give feedback.
-
@Tokics 感谢指出,我表述的有点模糊,已修改 |
Beta Was this translation helpful? Give feedback.
-
其实这个模版W的枚举方向错了,变成完全背包问题了 |
Beta Was this translation helpful? Give feedback.
-
东哥我想问一下这里装入的情况为什么不像01背包问题的状态转移方程一样使用 dp[i][j] = dp[i - 1][j] || dp[i-1][j-nums[i-1]];
// 不装入 装入 |
Beta Was this translation helpful? Give feedback.
-
这地方是有一个bug的,需要对wt进行一个排序 |
Beta Was this translation helpful? Give feedback.
-
“dp[i][w] 的定义如下:对于前 i 个物品,当前背包的容量为 w,...”在定义这里,w是不是可以理解为背包当前的负载? |
Beta Was this translation helpful? Give feedback.
-
力扣没有对应的题目,但牛客有:https://www.nowcoder.com/questionTerminal/708f0442863a46279cce582c4f508658? import java.util.Scanner;
public class Main {
/**
* @param w 物件重量
* @param v 物件价值
* @param C 背包容量
* @return
*/
public int knapsack01(int[] w, int[] v, int C) {
// 物件个数
int n = w.length;
// dp[i][j]: 使用容量i的背包,装前j个物品,最大收益
int[][] dp = new int[C + 1][n];
// 转移方程 dp[i][j] = max{ dp[i-w[j]][j-1], dp[i][j-1] }
for (int i = 0; i <= C; i++) {
for (int j = 0; j < n; j++) {
if (i == 0) {
dp[i][j] = 0;
continue;
}
if (j == 0) {
dp[i][0] = i >= w[j] ? v[j] : 0;
continue;
}
if (i >= w[j]) {
// 可以看出只和上方和左边有关系,所以C和n哪个循环在外无关系
dp[i][j] = Math.max(dp[i - w[j]][j - 1] + v[j], dp[i][j - 1]);
} else {
dp[i][j] = dp[i][j - 1];
}
}
}
return dp[C][n - 1];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int C = scanner.nextInt();
int n = scanner.nextInt();
int[] w = new int[n];
int[] v = new int[n];
for (int i = 0; i < n; i++) {
w[i] = scanner.nextInt();
v[i] = scanner.nextInt();
}
System.out.println(new Main().knapsack01(w, v, C));
}
} |
Beta Was this translation helpful? Give feedback.
-
怎么用递归(从上至下)的方式实现呢? |
Beta Was this translation helpful? Give feedback.
-
新手入门,这句表述我有一些困惑:你如果选择将第 i 个物品装进背包,那么第 i 个物品的价值 val[i-1] 肯定就到手了,接下来你就要在剩余容量 w - wt[i-1] 的限制下,在前 i - 1 个物品中挑选,求最大价值,即 dp[i-1][w - wt[i-1]]。 我理解上这是一个二维动态表,每次填表依赖的是左和上,而不是在 '在前i-1个物品中挑选'? |
Beta Was this translation helpful? Give feedback.
-
// 验证按照0-1背包定义也能解决。dp数组含义是能放入的最大重量,如果dp[n][w]重量刚好为总和的一半,就表示能分成两组满足各一半。 |
Beta Was this translation helpful? Give feedback.
-
文章链接点这里:经典动态规划:0-1 背包问题
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions