完全背包問題及Python代碼實(shí)現(xiàn)

上一節(jié)中这难,我們介紹了0-1背包問題,接下來葡秒,我們來學(xué)習(xí)一下背包問題的其他變形問題姻乓,今天要學(xué)習(xí)的是完全背包問題。

1眯牧、簡介

有 N 種物品和一個(gè)容量為 W 的背包蹋岩,每種物品都有無限件可用。第 i 種物品的重量是 w[i]学少,價(jià)值是 v[i]剪个。求解將哪些物品裝入背包可使這些物品的重量總和不超過背包容量,且價(jià)值總和最大旱易〗耍可以看到腿堤,與0-1背包問題不同的地方時(shí)阀坏,完全背包問題允許一件物品無限次的出現(xiàn)。

2笆檀、基本思路

這個(gè)問題非常類似于 0-1 背包問題忌堂,所不同的是每種物品有無限件。也就是從每 種物品的角度考慮酗洒,與它相關(guān)的策略已并非取或不取兩種士修,而是有取 0 件、取 1 件樱衷、取 2 件??等很多種棋嘲。如果仍然按照解 01 背包時(shí)的思路,令 f[i][w]表示 前 i 種物品恰放入一個(gè)容量為 w 的背包的最大權(quán)值矩桂。仍然可以按照每種物品不同 的策略寫出狀態(tài)轉(zhuǎn)移方程沸移,像這樣:
f[i][w]=max{f[i-1][w-kw[i]]+kw[i]|0<=kw[i]<=w}
這跟 0-1 背包問題一樣有 O(N
W)個(gè)狀態(tài)需要求解,但求解每個(gè)狀態(tài)的時(shí)間已經(jīng)不 是常數(shù)了侄榴,求解狀態(tài) f[i][v]的時(shí)間是 O(w/w[i])雹锣,總的復(fù)雜度是超過 O(WN)的。
將 0-1 背包問題的基本思路加以改進(jìn)癞蚕,得到了這樣一個(gè)清晰的方法蕊爵。這說明 0-1 背包問題的方程的確是很重要,可以推及其它類型的背包問題桦山。但我們還是試圖 改進(jìn)這個(gè)復(fù)雜度攒射。

3醋旦、簡單優(yōu)化

完全背包問題有一個(gè)很簡單有效的優(yōu)化,是這樣的:若兩件物品 i会放、j 滿足 w[i]<=w[j]且 v[i]>=v[j]浑度,則將物品 j 去掉,不用考慮鸦概。這個(gè)優(yōu)化的正確性顯 然:任何情況下都可將價(jià)值小費(fèi)用高得 j 換成物美價(jià)廉的 i箩张,得到至少不會(huì)更差 的方案。對(duì)于隨機(jī)生成的數(shù)據(jù)窗市,這個(gè)方法往往會(huì)大大減少物品的件數(shù)先慷,從而加快 速度。然而這個(gè)并不能改善最壞情況的復(fù)雜度咨察,因?yàn)橛锌赡芴貏e設(shè)計(jì)的數(shù)據(jù)可以 一件物品也去不掉论熙。
這個(gè)優(yōu)化可以簡單的 O(N^2)地實(shí)現(xiàn),一般都可以承受摄狱。另外脓诡,針對(duì)背包問題而 言,比較不錯(cuò)的一種方法是:首先將費(fèi)用大于 V 的物品去掉媒役,然后使用類似計(jì)數(shù) 排序的做法祝谚,計(jì)算出費(fèi)用相同的物品中價(jià)值最高的是哪個(gè),可以 O(W+N)地完成 這個(gè)優(yōu)化.

4酣衷、轉(zhuǎn)化為0-1背包問題

既然 0-1 背包問題是最基本的背包問題交惯,那么我們可以考慮把完全背包問題轉(zhuǎn)化 為 0-1 背包問題來解。最簡單的想法是穿仪,考慮到第 i 種物品最多選 W/w[i]件席爽,于 是可以把第 i 種物品轉(zhuǎn)化為 W/w[i]件費(fèi)用及價(jià)值均不變的物品,然后求解這個(gè) 0-1 背包問題啊片。這樣完全沒有改進(jìn)基本思路的時(shí)間復(fù)雜度只锻,但這畢竟給了我們將 完全背包問題轉(zhuǎn)化為 0-1 背包問題的思路:將一種物品拆成多件物品。
更高效的轉(zhuǎn)化方法是:把第 i 種物品拆成費(fèi)用為 w[i]2^k紫谷、價(jià)值為 v[i]2^k 的 若干件物品齐饮,其中 k 滿足 w[i]*2^k<=W。這是二進(jìn)制的思想碴里,因?yàn)椴还茏顑?yōu)策略 選幾件第 i 種物品沈矿,總可以表示成若干個(gè) 2^k 件物品的和。這樣把每種物品拆成 O(log(W/w[i]))件物品咬腋,是一個(gè)很大的改進(jìn)羹膳。

但我們有更優(yōu)的 O(VN)的算法。

5根竿、O(VN)的算法

這個(gè)算法使用一維數(shù)組陵像,先看偽代碼:

   for i=1..N
       for w=0..W
f[w]=max{f[w],f[w-cost]+weight}

你會(huì)發(fā)現(xiàn)就珠,這個(gè)偽代碼與0-1背包問題只有 的循環(huán)次序不同而已。為什么這樣 一改就可行呢?首先想想為什么 0-1背包問題中要按照 w=W..0 的逆序來循環(huán)醒颖。這是因?yàn)?要保證第 i 次循環(huán)中的狀態(tài) f[i][w]是由狀態(tài) f[i-1][w-w[i]]遞推而來妻怎。換句話 說,這正是為了保證每件物品只選一次泞歉,保證在考慮“選入第 i 件物品”這件策 略時(shí)逼侦,依據(jù)的是一個(gè)絕無已經(jīng)選入第 i 件物品的子結(jié)果 f[i-1][w-w[i]]。而現(xiàn) 在完全背包的特點(diǎn)恰是每種物品可選無限件腰耙,所以在考慮“加選一件第 i 種物 品”這種策略時(shí)榛丢,卻正需要一個(gè)可能已選入第 i 種物品的子結(jié)果 f[i][w-w[i]], 所以就可以并且必須采用 w=0..W 的順序循環(huán)挺庞。這就是這個(gè)簡單的程序?yàn)楹纬闪?的道理晰赞。

6、完全背包問題Python實(shí)現(xiàn)

基于上面的思路选侨,完全背包問題Python實(shí)現(xiàn)代碼如下:

def solve3(vlist,wlist,totalWeight,totalLength):
    """完全背包問題"""
    resArr = np.zeros((totalWeight)+1,dtype=np.int32)
    for i in range(1,totalLength+1):
        for j in range(1,totalWeight+1):
            if wlist[i] <= j:
                resArr[j] = max(resArr[j],resArr[j-wlist[i]]+vlist[i])
    return resArr[-1]

if __name__ == '__main__':
    v = [0,60,100,120]
    w = [0,10,20,30]
    weight = 50
    n = 3
    result = solve3(v,w,weight,n)
    print(result)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掖鱼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子援制,更是在濱河造成了極大的恐慌戏挡,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隘谣,死亡現(xiàn)場離奇詭異增拥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)寻歧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秩仆,“玉大人码泛,你說我怎么就攤上這事〕嗡#” “怎么了噪珊?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長齐莲。 經(jīng)常有香客問我痢站,道長,這世上最難降的妖魔是什么选酗? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任阵难,我火速辦了婚禮,結(jié)果婚禮上芒填,老公的妹妹穿的比我還像新娘呜叫。我一直安慰自己空繁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布朱庆。 她就那樣靜靜地躺著盛泡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娱颊。 梳的紋絲不亂的頭發(fā)上傲诵,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音箱硕,去河邊找鬼掰吕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛颅痊,可吹牛的內(nèi)容都是我干的殖熟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼斑响,長吁一口氣:“原來是場噩夢啊……” “哼菱属!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起舰罚,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤纽门,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后营罢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赏陵,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年饲漾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蝙搔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡考传,死狀恐怖吃型,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情僚楞,我是刑警寧澤勤晚,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站泉褐,受9級(jí)特大地震影響赐写,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜膜赃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一挺邀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦悠夯、人聲如沸癌淮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乳蓄。三九已至,卻和暖如春夕膀,著一層夾襖步出監(jiān)牢的瞬間虚倒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國打工产舞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魂奥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓易猫,卻偏偏與公主長得像耻煤,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子准颓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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