如果是直接從來沒聽過揹包問題,可以先看文字講解慢慢了解 這是幹什麼的。
如果做過揹包類問題,可以先看影片,很多內容,是自己平時沒有考慮到位的。
揹包問題,力扣上沒有原題,大家先了解理論,今天就安排一道具體題目。
詳細布置
01揹包問題 二維
https://programmercarl.com/揹包理論基礎01揹包-1.html
影片講解:https://www.bilibili.com/video/BV1cg411g7Y6
二維比較好理解
function testWeightBagProblem (weight, value, size) {
const dp = new Array(weight.length).fill(0).map(()=>new Array(size+1).fill(0));
for (i=weight[0];i<=size;i++) {
dp[0][i] = value[0];
}
for (let i=1;i<weight.length;i++) {
for (let j=0;j<=size;j++) {
if (j<weight[i]) {
dp[i][j] = dp[i-1][j];
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);
}
}
}
console.table(dp)
return dp[weight.length-1][size]
}
``
01揹包問題 一維
https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-2.html
影片講解:https://www.bilibili.com/video/BV1BU4y177kY
一維難理解,主要理解為什麼要從後遍歷,因為從前遍歷有可能會把前面的物品新增多次
從二維陣列推導公式來看一維陣列,dp[i]的值需要依靠上一組陣列的dp[i-1]的值,如果從前往後遍歷,就會有問題
另外j為什麼要大於等於wight[i],因為j是容量,如果小於,其實就完全複製就行,不用計算
function testWeightBagProblem2(wight, value, size) {
const len = wight.length;
const dp = new Array(size+1).fill(0);
for (let i=0;i<len;i++) {
for (let j=size;j>=wight[i];j--) {
dp[j] = Math.max(dp[j], dp[j - wight[i]]+value[i]);
}
console.log(dp)
}
console.log(dp)
return dp[size];
}
416. 分割等和子集
本題是 01揹包的應用類題目
https://programmercarl.com/0416.%E5%88%86%E5%89%B2%E7%AD%89%E5%92%8C%E5%AD%90%E9%9B%86.html
影片講解:https://www.bilibili.com/video/BV1rt4y1N7jE
/**
-
@param {number[]} nums
-
@return {boolean}
*/
var canPartition = function(nums) {
let total = 0;
for (let i=0;i<nums.length;i++) {
total+=nums[i];
}if (total%2 === 1) return false;
const dp = new Array(total/2 + 1).fill(0);
for (let i=0;i<nums.length;i++) {
for(let j=total/2;j>=nums[i];j--){
dp[j] = Math.max(dp[j], dp[j-nums[i]]+nums[i]);
if (dp[j]===total/2) {
return true;
}
}
}return false;
};