動(dòng)態(tài)規(guī)劃算法二 背包問(wèn)題

動(dòng)態(tài)規(guī)劃專題

https://labuladong.gitbook.io/algo/dong-tai-gui-hua-xi-lie/dong-tai-gui-hua-xiang-jie-jin-

「0-1背包問(wèn)題描述」

現(xiàn)在有一個(gè)可裝載重量為 W 的背包和 N 個(gè)物品滑凉,每個(gè)物品有重量和價(jià)值兩個(gè)屬性。其中第 i 個(gè)物品的重量為 wt[i-1]喘帚,價(jià)值為 val[i-1]畅姊,現(xiàn)在讓你用這個(gè)背包裝物品,最多能裝的價(jià)值是多少吹由?

例如:

W = 10, N = 5

wt = [2, 2, 6, 5, 4]

val = [6, 3, 5, 4, 6]

返回 15若未,因?yàn)榭梢匝b [2,2,4] 重量的物品,價(jià)值分別 [6,3,6]

題目中 0-1 指的是背包裝物品時(shí)倾鲫,要么裝整個(gè)物品粗合、要么不裝,不能只裝取部分乌昔。

題目分析

因?yàn)楸嘲兄亓肯拗葡毒危援?dāng)我們遍歷物品時(shí),無(wú)法確定物品是否被裝入背包磕道,就更難以找到裝某一物品時(shí)與之前狀態(tài)的關(guān)聯(lián)供屉。動(dòng)態(tài)規(guī)劃會(huì)強(qiáng)調(diào)“狀態(tài)”,通過(guò)自定義的一維或二維數(shù)組為我們將物品裝入背包這個(gè)行為定義成狀態(tài)的變化,從而找到與上一次裝物品之間的關(guān)聯(lián)伶丐。

動(dòng)態(tài)規(guī)劃英文 dynamic programming悼做,所以定義相關(guān)的狀態(tài)數(shù)組多用 dp, 本題目中就是通過(guò)定義二維數(shù)組、在 Python 中即嵌套列表來(lái)實(shí)現(xiàn)撵割。

背包問(wèn)題中贿堰,用 dp [ i ] [ j ] 表示在物品列表中的前 i 件物品操作完、此時(shí)背包容量為 j 的狀態(tài)下啡彬,背包所能裝的最大價(jià)值羹与,恰好對(duì)應(yīng)了題目所求,求容量為 W 的背包庶灿、 N 個(gè)物品所實(shí)現(xiàn)最大價(jià)值即 dp [ N ] [ W ]? 對(duì)應(yīng)的值纵搁。

為何要定義這么一個(gè)奇怪的狀態(tài)呢?就是為了找尋裝物品時(shí)不同狀態(tài)間的關(guān)系往踢,從而建立狀態(tài)轉(zhuǎn)移方程腾誉。在裝第 i 件物品時(shí),對(duì)應(yīng)題目中的重量和價(jià)值列表峻呕,該物品重量為 wt[i-1]利职、價(jià)值為 val[i-1]。

在操作這第 i 件物品之前瘦癌,背包狀態(tài)處于 dp [ i-1 ] [ j ] 猪贪,物品 -1、容量不變讯私。進(jìn)行到第 i 件了热押,要么裝、要么不裝就這兩種選擇:裝的話斤寇,新的狀態(tài)要在之前的價(jià)值上添加新物品的價(jià)值桶癣;不裝的話,那么新?tīng)顟B(tài)與之前狀態(tài)的價(jià)值是相等的娘锁。這便是背包問(wèn)題狀態(tài)轉(zhuǎn)移關(guān)鍵所在牙寞。有種建立遞歸關(guān)系的意思,所以要找到初始狀態(tài)值莫秆,在 i = 0 或 j = 0 時(shí)碎税,一個(gè)是 0 件物品、一個(gè)是背包容量為 0馏锡,其價(jià)值對(duì)應(yīng)為 0雷蹂。之后的狀態(tài)值在此基礎(chǔ)上可以不斷找到得出。

代碼實(shí)現(xiàn)

因?yàn)楸绢}不是 LeetCode 原題杯道,所以解法代碼沒(méi)有沿用 Class 那種格式匪煌,只是定義了函數(shù):

# n 對(duì)應(yīng)個(gè)數(shù)责蝠,c 對(duì)應(yīng)背包容量,w 為物品重量列表萎庭,v 物品價(jià)值列表

def bag_value(n,c,w,v):

? # 嵌套的列表解析式生成 c x n 的二維數(shù)組霜医、列表

? ? dp = [[None for j in range(c+1)] for i in range(n+1)]

? ? # 為初始狀態(tài) i=0 或 j=0 時(shí)賦值 0

? ? for i in range(n+1):

? ? ? ? for j in range(c+1):

? ? ? ? ? ? if i == 0:

? ? ? ? ? ? ? ? dp[i][j]=0

? ? ? ? ? ? if j == 0:

? ? ? ? ? ? ? ? dp[i][j]=0

? ? # 仍然遍歷二維數(shù)組? ? ? ? ? ?

? ? for i in range(1,n+1):

? ? ? ? for j in range(1,c+1):

? ? ? ? ? # 若背包容量小于要裝的物品重量,那么該物品不會(huì)被裝入驳规、狀態(tài)不變

? ? ? ? ? ? if j<w[i-1]:

? ? ? ? ? ? ? ? dp[i][j] = dp[i-1][j]

? ? ? ? ? ? # 若有可能裝該物品肴敛,取裝或不裝該物品狀態(tài)下最大價(jià)值

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? dp[i][j] = max(dp[i-1][j-w[i-1]]+v[i-1],dp[i-1][j])

? ? # 最終返回 n、c 值下的 dp 價(jià)值

? ? return dp[n][c]

n = 5

c = 10

w = [2, 2, 6, 5, 4]

v = [6, 3, 5, 4, 6]

result = bag_value(n,c,w,v)

# 可以得到 result 值為 15

這里值得注意的是吗购,在不確定是否裝該物品時(shí)医男,對(duì)上一個(gè)狀態(tài)的取值并沒(méi)有取我們之前提到的 dp [ i-1 ] [ j ] 而是對(duì)這里的背包容量處理、調(diào)整至最大容量減去第 i 件物品的重量捻勉,這是為了保證裝完該物品后不超出背包容量限制镀梭,而 dp 本身對(duì)背包容量是有遍歷的,所以選取的是最精準(zhǔn)的上一狀態(tài)踱启。

感想

刷題刷到動(dòng)態(tài)規(guī)劃报账,很大的感受是我這刷題實(shí)施得太晚了,早幾年就好了埠偿,之前對(duì)這些概念透罢、算法完全沒(méi)有意識(shí)。現(xiàn)在補(bǔ)過(guò)冠蒋,只能說(shuō)好過(guò)之后來(lái)補(bǔ)羽圃。

同時(shí),潛意識(shí)里就覺(jué)著動(dòng)態(tài)規(guī)劃很難浊服,所以選的策略是跳出題目统屈,看有經(jīng)驗(yàn)大牛的整理專題胚吁,在他們的引領(lǐng)下熟悉這些題目的套路牙躺,先學(xué)習(xí)、掌握要點(diǎn)后再通過(guò)練習(xí)來(lái)提高熟練度腕扶。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末孽拷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子半抱,更是在濱河造成了極大的恐慌脓恕,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窿侈,死亡現(xiàn)場(chǎng)離奇詭異炼幔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)史简,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門乃秀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事跺讯∈嗷撸” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵刀脏,是天一觀的道長(zhǎng)局荚。 經(jīng)常有香客問(wèn)我,道長(zhǎng)愈污,這世上最難降的妖魔是什么耀态? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮钙畔,結(jié)果婚禮上茫陆,老公的妹妹穿的比我還像新娘。我一直安慰自己擎析,他們只是感情好簿盅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著揍魂,像睡著了一般桨醋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上现斋,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天喜最,我揣著相機(jī)與錄音,去河邊找鬼庄蹋。 笑死瞬内,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的限书。 我是一名探鬼主播虫蝶,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼倦西!你這毒婦竟也來(lái)了能真?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扰柠,失蹤者是張志新(化名)和其女友劉穎粉铐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卤档,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝙泼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劝枣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汤踏。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倡缠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出茎活,到底是詐尸還是另有隱情昙沦,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布载荔,位于F島的核電站盾饮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏懒熙。R本人自食惡果不足惜丘损,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望工扎。 院中可真熱鬧徘钥,春花似錦、人聲如沸肢娘。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)橱健。三九已至而钞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拘荡,已是汗流浹背臼节。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留珊皿,地道東北人网缝。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蟋定,于是被迫代替她去往敵國(guó)和親粉臊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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