代碼隨想錄算法訓(xùn)練營第三十天|LeetCode 416. 分割等和子集

今天是動態(tài)規(guī)劃的第三天癌蚁!來到了萬眾矚目的 背包問題幻梯!

首先,什么是背包問題努释?簡單來說就是有一個(gè)背包,容量已知咬摇,然后有幾個(gè)物品伐蒂,已知物品的重量與價(jià)值,求如何放物品使得背包內(nèi)物品的價(jià)值最高肛鹏。根據(jù)物品的數(shù)量可以把背包問題細(xì)分為01背包和完全背包等更細(xì)的分類:


背包問題分類

鑒于01背包是各類背包問題的核心基礎(chǔ)逸邦,因此本篇優(yōu)先探索01背包問題的核心解法及其內(nèi)在邏輯。

01背包??問題概述:有n件物品和一個(gè)最多能裝w重量的背包在扰。第i件物品的重量為weight[i]缕减、價(jià)值為value[i]。每件物品最多只能用一次芒珠。求解將那些物品裝入背包里 可使得背包總價(jià)值最大桥狡?


01背包問題

看到問題,首先我們得想到的是 這個(gè)問題的暴力解法應(yīng)該是如何皱卓?這點(diǎn)其實(shí)不難想裹芝,對于每個(gè)物品,其實(shí)就是選與不選兩種情況娜汁,因此我們可以用回溯法搜索出所有的情況嫂易,對于n個(gè)物品而言,時(shí)間復(fù)雜度是O(2 ^ n)掐禁。所以暴力解法不是做不出來怜械,而是他是指數(shù)級別的復(fù)雜度颅和,所以需要動態(tài)規(guī)劃來優(yōu)化。

下面以一個(gè)例子來講解:
背包重量為4缕允,
物品0 重量1 價(jià)值15
物品1 重量3 價(jià)值20
物品2 重量4 價(jià)值30
求背包的最大價(jià)值峡扩。

解法是 二維dp數(shù)組解法:
還是用動態(tài)規(guī)劃五部曲來分析一下:

  1. 在分析二維數(shù)組的含義之前,我們現(xiàn)探究一下為什么要使用二維數(shù)組---因?yàn)槲覀冇袃蓚€(gè)維度需要表示---物品 和 背包容量灼芭。如圖所示有额,二維數(shù)組為dp[i][j]:


    二維數(shù)組dp[i][j]

    由圖可知,我們使用i表示物品彼绷,j表示背包容量/背包重量巍佑。(當(dāng)然這只是習(xí)慣問題,你也可以用j來表示物品)寄悯。根據(jù)動態(tài)規(guī)劃 是 通過子問題的求解推導(dǎo)出整體的最優(yōu)解 的思路萤衰,我們可以一步步嘗試填寫一下表格:例如把物品0放入背包:


    物品0放入背包

    因?yàn)槲锲?只有一個(gè),所以最多就只能放一次猜旬,這是為什么當(dāng)容量>=2之后脆栋,總價(jià)值依然是15的原因。接下來嘗試把物品1放入背包:
    物品1放入背包

    背包容量為3時(shí)洒擦,可選擇放物品0或物品1椿争,顯然放物品1的價(jià)值更高,所以選擇放物品1或取更高的價(jià)值20.
    背包容量為4時(shí)熟嫩,上一行狀態(tài)不變秦踪,背包只能放物品0;這一行除了物品0之外還有物品1可以選掸茅,而且可以兩者都放得下椅邓,所以最高價(jià)值為35.

由以上例子的分析,我們不難發(fā)現(xiàn)dp數(shù)組的含義:dp[i][j]表示在[0-i]的物品里任意選擇昧狮,放進(jìn)容量為j的背包景馁,所產(chǎn)生的最大價(jià)值。舉例說明:在上圖中dp[1][4]表示在物品0和物品1里任意選擇逗鸣,使得放入容量為4的背包時(shí) 產(chǎn)生的最大價(jià)值合住。

  1. 遞推公式
    這一步就是要確定dp[i][j]可由哪些方向推到而來。還是用dp[1][4]舉例慕购,對于物品1而已有兩種情況:1??把物品1放入背包 2??不把物品1放入背包
    如果不把物品1放入背包聊疲,那么背包的價(jià)值應(yīng)該是dp[0][4],即容量為4時(shí)沪悲,只考慮是否放物品0 的最大價(jià)值:


    不放物品1時(shí)背包價(jià)值的推導(dǎo)方向

如果把物品1放入背包获洲,那么價(jià)值應(yīng)該是物品1的價(jià)值 加上 背包剩余容量時(shí)考慮是否放入物品0的價(jià)值。帶入數(shù)值就是 背包剩余容量1時(shí)殿如,是否放入物品0的價(jià)值dp[0][1]:


放入物品1時(shí)背包價(jià)值的推導(dǎo)方向

因此贡珊,我們只需將兩種方式取最大值 即可 求的 放與不放物品1的最大值:
dp[1][4] = max(dp[0][4], dp[0][1] + value[1])
將以上公式抽象化可以得到 不放物品i的價(jià)值為 dp[i-1][j]最爬;放物品i的價(jià)值為dp[i-1][j-weight[i]] + value[i]

綜上所述,遞推公式為 dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])

  1. dp數(shù)組的初始化
    關(guān)于初始化门岔,不是瞎貓碰上死耗子爱致,胡亂一猜。一定要與定義吻合寒随。
    從dp[i][j]的定義出發(fā)糠悯,當(dāng)背包容量為0時(shí),無論物品有哪些妻往,價(jià)值都是為0:


    背包容量為0時(shí)的初始化

    由遞推公式可知 i 都是由 i-1 推導(dǎo)而來互艾,也就是圖中的下一層都是由上一層的某一個(gè)推導(dǎo)而來,因此第一行的數(shù)據(jù)讯泣,即i=0時(shí)纫普,就一定要初始化。對此也不難好渠,當(dāng)容量不足以放物品0時(shí)昨稼,價(jià)值也就不存在;當(dāng)重量足夠放物品0時(shí)拳锚,價(jià)值一直時(shí)物品0的價(jià)值假栓。


    dp數(shù)組第一行初始化

    至于其他部分,鑒于在后續(xù)遍歷中都會被覆蓋霍掺,因此是多少都無所謂但指,所以為了方便我們就都初始化為0就好了。
    完整的dp數(shù)組初始化
  2. 確定遍歷順序抗楔。
    從圖中可以看出,遍歷有兩個(gè)維度:物品 和 背包重量拦坠。至于兩個(gè)維度先遍歷哪個(gè)连躏,我們得理解遞推方向的本質(zhì)。
    根據(jù)遞推公式 dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]) 可以看出dp[i][j]是由dp[i-1][j]和dp[i-1][j-weight[i]]推出來的贞滨。而這兩部分都在dp[i][j]的左上部分(包括正上方)入热,所以只需保證在求得dp[i][j]之前,左上部分(包括正上方)是有值的就可以了晓铆。接下來我們看看兩種遍歷順序能否保證dp[i][j]左上方有值勺良。
    1??先遍歷物品后遍歷背包容量


    先遍歷物品

    可以看到,遍歷順序是骄噪,從左到右尚困,然后一行一行向下遍歷(圖中藍(lán)色箭頭)那在遍歷到紅框時(shí),他的左上部分時(shí)已經(jīng)有值了的链蕊,所以這種遍歷方式可行事甜。
    2??先遍歷背包容量后遍歷物品


    先遍歷背包容量

    遍歷順序是從上到下遍歷谬泌,然后一列一列向右進(jìn)行(圖中藍(lán)色箭頭,順序是從左往右)逻谦。因此在遍歷到紅色方框的時(shí)候掌实,左上角也是已經(jīng)有值了,因此這種方式也可行邦马。
    所以雖然兩種方式的遍歷順序不同贱鼻,但是都滿足dp[i][j]需要的數(shù)據(jù)就是左上角這一需求,所以都可以滋将。
  3. 舉例推導(dǎo)dp數(shù)組 (打印結(jié)果)


    dp數(shù)組結(jié)果

    本例最終結(jié)果就如上圖所示邻悬。然后本題在LeetCode沒有原題,所以暫時(shí)不出具體題目耕渴。本篇旨在分析清楚01背包問題的基本底層邏輯拘悦,希望給背包問題打好基礎(chǔ)。背包問題只是基礎(chǔ)橱脸,在LeetCode中需要掌握一些實(shí)際應(yīng)用础米。

(稍后補(bǔ)充例題講解) - - - - -

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市添诉,隨后出現(xiàn)的幾起案子屁桑,更是在濱河造成了極大的恐慌,老刑警劉巖栏赴,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蘑斧,死亡現(xiàn)場離奇詭異,居然都是意外死亡须眷,警方通過查閱死者的電腦和手機(jī)竖瘾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來花颗,“玉大人捕传,你說我怎么就攤上這事±┤埃” “怎么了庸论?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長棒呛。 經(jīng)常有香客問我聂示,道長,這世上最難降的妖魔是什么簇秒? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任鱼喉,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蒲凶。我一直安慰自己气筋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布旋圆。 她就那樣靜靜地躺著宠默,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灵巧。 梳的紋絲不亂的頭發(fā)上搀矫,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音刻肄,去河邊找鬼瓤球。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敏弃,可吹牛的內(nèi)容都是我干的卦羡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼麦到,長吁一口氣:“原來是場噩夢啊……” “哼绿饵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瓶颠,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拟赊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后粹淋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吸祟,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年桃移,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屋匕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡借杰,死狀恐怖炒瘟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情第步,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布缘琅,位于F島的核電站粘都,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏刷袍。R本人自食惡果不足惜翩隧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呻纹。 院中可真熱鬧堆生,春花似錦专缠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蔗怠,卻和暖如春墩弯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寞射。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工渔工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桥温。 一個(gè)月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓引矩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侵浸。 傳聞我的和親對象是個(gè)殘疾皇子旺韭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容