0-1背包问题
题目

给你一个可装载重量为W的背包和N个物品,每个物品有重量和价值两个属性。其中第i个物品的重量为wt[i],价值为val[i],现在让你用这个背包装物品,最多能装的价值是多少?
举个简单的例子,输入如下:
N = 3, W = 4
wt = [2, 1, 3]
val = [4, 2, 3]
算法返回 6,选择前两件物品装进背包,总重量 3 小于W,可以获得最大价值 6。
题目就是这么简单,一个典型的动态规划问题。这个题目中的物品不可以分割,要么装进包里,要么不装,不能说切成两块装一半。这也许就是 0-1 背包这个名词的来历。
思路
- 利用二维dp数组,计算最大价值,当物品为一个时候,能怎么装,然后当物品为两个时候,又能怎么装才能使价值最大...以此类推,直到达到列出所有的物品和背包的最大容量时,dp[n][m]就是我们要求的最大能获得的价值
- 如果一个物品的重量大于当前背包的最大承重,那么就直接不装
- 如果物品小于最大承重,再进行择优:比较转和不装哪个价值大,那么就选它
代码实现
public static int knapsack(int w, int n, int[] wt, int[] val) {
// 定义dp数组,dp的每一个元素代表背包不同容量和不同物品重量对应得最大的价值
int[][] dp = new int[n + 1][w + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= w; j++) {
// 如果当前单个物品的重量超过了当前背包的最大重量,则装不下,就不装了(wt[i-1]: 索引从1开始)
if (j < wt[i - 1]) {
// 不装
dp[i][j] = dp[i - 1][j];
} else {
// 装入或则不装入背包,择优
// dp[i-1][j - wt[i-1]]:将当前的背包重量减去当前要装入的物品的重量,然后去查找剩下的重量的对应的最大的值(尽量让背包装满)
// dp[i-1][j] 即不装入背包
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - wt[i - 1]] + val[i - 1]);
}
}
}
return dp[n][w];
}
复杂度分析
- 时间复杂度为O(nw)
- 空间复杂度为O(nw)
我走得很慢,但我从不后退!

浙公网安备 33010602011771号