dp揹包問題總結

2021-10-23 20:52:34 字數 4079 閱讀 3748

**leetcode題解回答:[jackie.yl]

常見的揹包問題分為三種:

組合問題公式

dp[i]

+= dp[i-num]

true、false問題公式

dp[i]

= dp[i]

or dp[i-num]

最大最小問題公式

dp[i]

=min

(dp[i]

, dp[i-num]+1

)或者dp[i]

=max

(dp[i]

, dp[i-num]+1

)

以上三組公式是解決對應問題的核心公式。

當然拿到問題後,需要做到以下幾個步驟:

1.分析是否為揹包問題。

2.是以上三種揹包問題中的哪一種。

3.是0-1揹包問題還是完全揹包問題。也就是題目給的nums陣列中的元素是否可以重複使用。

4.如果是組合問題,是否需要考慮元素之間的順序。需要考慮順序有順序的解法,不需要考慮順序又有對應的解法。

接下來講一下揹包問題的判定

揹包問題具備的特徵:給定乙個target,target可以是數字也可以是字串,再給定乙個陣列nums,nums中裝的可能是數字,也可能是字串,問:能否使用nums中的元素做各種排列組合得到target。

揹包問題技巧:

1.如果是0-1揹包,即陣列中的元素不可重複使用,nums放在外迴圈,target在內迴圈,且內迴圈倒序;

for num in nums:

for i in range

(target, nums-1,

-1):

2.如果是完全揹包,即陣列中的元素可重複使用,nums放在外迴圈,target在內迴圈。且內迴圈正序。

for num in nums:

for i in range

(nums, target+1)

:

3.如果組合問題需考慮元素之間的順序,需將target放在外迴圈,將nums放在內迴圈。

for i in range(1

, target+1)

:for num in nums:

例題:

組合注意區分零錢兌換||與組合總和4兩個問題是不一樣的,零錢兌換對組合順序無要求,而組合總和對組合順序還有要求不同也算,而這種不同只需要**進行內外層迴圈互換一下即可。

518. 零錢兌換 ii

class

solution

}return dp[amount];}

};

494. 目標和

這個題還是比較神奇的,換乙個角度來看這道題轉化為了乙個標準的01揹包問題:

把所有符號為正的數總和設為乙個揹包的容量,容量為x;把所有符號為負的數總和設為乙個揹包的容量,容量為y。在給定的陣列中,有多少種選擇方法讓揹包裝滿。令sum為陣列的總和,則x+y = sum。而兩個揹包的差為s,則x-y=s。從而求得x=(s+sum)/2。

基於上述分析,題目轉換為揹包問題:給定乙個陣列和乙個容量為x的揹包,求有多少種方式讓揹包裝滿。

class

solutionif(

(s+sum)%2

!=0)return0;

if(s>sum)

return0;

long

long len =

(s+sum)/2

;long

long

* dp =

newlong

long

[len+1]

;//dp陣列的意義為使用nums的數湊成的方法數

//int dp[len+1] = ;

memset

(dp,0,

sizeof

(long

long)*

(len+1)

);dp[0]

=1;for

(int i =

0;i!=nums.

size()

;i++)}

return dp[len];}

};

377. 組合總和 ⅳ

class

solution

}return dp[target];}

};

最大值最小值問題

474. 一和零

dp陣列含義:dp[i][j代表使用i個0與j個1所能拼出的最多的字串數量

class

solution

}for

(int k =

0;k!=strs.

size()

;k++)}

}return dp[m]

[n];}}

;

322. 零錢兌換

求最小數量,min

當 i0i0 時無法用硬幣組成,為 0 。當 i<0i<0 時,忽略 f(i)f(i)

f(i) 最小硬幣數量

f(0) 0 //金額為0不能由硬幣組成

f(1) 1 //f(1)=min(f(1-1),f(1-2),f(1-5))+1=1f(1)=min(f(1−1),f(1−2),f(1−5))+1=1

f(2) 1 //f(2)=min(f(2-1),f(2-2),f(2-5))+1=1f(2)=min(f(2−1),f(2−2),f(2−5))+1=1

f(3) 2 //f(3)=min(f(3-1),f(3-2),f(3-5))+1=2f(3)=min(f(3−1),f(3−2),f(3−5))+1=2

f(4) 2 //f(4)=min(f(4-1),f(4-2),f(4-5))+1=2f(4)=min(f(4−1),f(4−2),f(4−5))+1=2

… …f(11) 3 //f(11)=min(f(11-1),f(11-2),f(11-5))+1=3f(11)=min(f(11−1),f(11−2),f(11−5))+1=3

class

solution

}return dp[amount]

>=amount+1?

-1:dp[amount];}

};

ture false 問題

416. 分割等和子集

這個不能求子集,測試用例會卡住,dp直接照搬給出的套路即可,這是乙個01揹包問題湊數,記得在前面加上陣列和的判定可以直接返回false。dp陣列的含義為dp[i]該子集能否湊出i

class

solution

if(sum%2==

1)return

false

; vector<

bool

>

dp(sum/2+

1,false);

dp[0]

=true

;for

(int i =

0;i!=nums.

size()

;i++)}

//vectortrack;

//backtrack(nums,0,0,sum);

return dp[sum/2]

;}};

139. 單詞拆分

dp陣列的含義為dp[i],s的前i個字元能否能夠由字典裡的字串組成。

class

solution

return1;

}bool

wordbreak

(string s, vector

& worddict)

}//return check(0,worddict[0],s);

return dp[n];}

};

DP 揹包問題

大牛 以下使用滾到陣列 若輸入要求一般,可以邊定義狀態邊輸入,不需儲存 memset f,0,sizeof int n 若求最小值,除 f 0 其餘初始化為 inf,f 0 0是必須的 求最大最小都一樣 確保有從無到有的起點 0 1揹包 一般形式 f i v max f i 1 v f i 1 v ...

揹包問題 DP

01揹包 現在有1個體積為mmax的揹包和n種物品 每種物品只有1個 每種物品的體積和價值分別是v i 和w i 求這個揹包最多可以裝價值多少的物品。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不放。用子問題定義狀態 設f i j 表示前i件物品恰放入乙個容量為j的揹包可以獲得的最大...

DP 揹包問題

小明同學在參加一場考試,考試時間2個小時。試卷上一共有n道題目,小明要在規定時間內,完成一定數量的題目。考試中不限制試題作答順序,對於 i 第道題目,小明有三種不同的策略可以選擇 1 直接跳過這道題目,不花費時間,本題得0分。2 只做一部分題目,花費pi分鐘的時間,本題可以得到ai分。3 做完整個題...