1. 0-1 背包问题
给定一个数组 weight 代表物品的重量,w 代表背包的总容量,每个物品只能装一次,求背包最多能装下多少重量的物品。
物品的重量是 [2, 2, 4, 6, 3],背包重量是 9,这种情况下最优解是 9
var knapsack = function (weight, w) {
let n = weight.length
let states = []
// 对第一行进行特殊处理
states.push(new Array(w + 1).fill(0))
states[0][0] = 1
if(weight[0] <= w) states[0][weight[0]] = 1
for (let i = 1; i < n; i++){
states.push(new Array(w + 1).fill(0))
// 不把第i个物品放入背包
for (let j = 0; j <= w; j++){
if(states[i - 1][j]) states[i][j] = 1
}
// 把第i个物品放入背包
for (let j = 0; j <= w - weight[i]; j++){
if(states[i - 1][j]) states[i][j + weight[i]] = 1
}
}
for (let i = w; i >= 0; i--){
if(states[n - 1][i]) return i
}
}
2. 0-1 背包问题升级版
给定一个数组 weight 代表物品的重量, 数组 value 代表物品的价值,w 代表背包的总容量,每个物品只能装一次,求背包
最多能装下价值多少的物品。
物品的重量是 [2, 2, 4, 6, 3],物品的价值是[3, 4, 8, 9, 6],背包重量是 9,这种情况下最优解是 18
var knapsack = function (weight, value, w) {
let n = weight.length
let states = []
// 对第一行进行特殊处理
states.push(new Array(w + 1).fill(-1))
states[0][0] = 0
if (weight[0] <= w) states[0][weight[0]] = value[0]
for (let i = 1; i < n; i++) {
states.push(new Array(w + 1).fill(-1))
// 不把第i个物品放入背包
for (let j = 0; j <= w; j++) {
if (states[i - 1][j] >= 0) states[i][j] = states[i - 1][j]
}
// 把第i个物品放入背包
for (let j = 0; j <= w - weight[i]; j++) {
if (states[i - 1][j] >= 0) {
// 重量相同时,取价值更大的情况
states[i][j + weight[i]] = Math.max(states[i][j + weight[i]], states[i - 1][j] + value[i])
}
}
}
let max = -1
for (let i = w; i >= 0; i--){
if(states[n - 1][i] > max) max = states[n - 1][i]
}
return max
}
3. 分割等和子集
实现思路:将数组元素和除2作为target,转换为01背包问题
var canPartition = function(nums) {
let n = nums.length;
let target = nums.reduce((a, b) => a + b) / 2;
if(Math.floor(target) !== target) return false;
let dp = [];
dp.push(new Array(target + 1).fill(false))
dp[0][0] = true
if(nums[0] <= target) dp[0][nums[0]] = true
for(let i = 1; i < n; i++){
dp.push(new Array(target + 1).fill(false));
for(let j = 0; j <= target; j++){
if(dp[i - 1][j] > 0) dp[i][j] = true;
}
for(let j = 0; j <= target - nums[i]; j++){
if(dp[i - 1