经典动态规划: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.
-
蓝桥杯里有这题 |
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.
-
打卡。 |
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.
-
怎么用递归(从上至下)的方式实现呢? |
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:经典动态规划:0-1 背包问题
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions