關於01揹包問題的動態規劃思路

2021-08-31 05:17:15 字數 4974 閱讀 4713

大二在讀生自己的總結,求大牛不要噴。。。

要做動態規劃題最重要的就是找思路,怎麼分解這個問題,把這個大問題化為小問題,小問題再化為更小的問題,最後就能做出來了。

動態規劃裡有乙個經典的01揹包問題,乙個揹包的容量為k,然後有n個不同的物品大小分別為v1,v2,v3…求這個揹包k最多能容納多少物品容量和。

刷了好幾道這種題,現在已經知道大概思路了,所以來總結一下。

做01揹包問題的動態規劃,可以用乙個一維陣列dg[i]

dg[i]則表示,在容量為i的揹包下,最多能裝的物品容量和為dg[i]

而要求dg[i]的話

假設乙個物品容量為v1,那麼dg[i]=max(dg[i],dg[i-v1]+v1)

看式子可能不好理解,舉個例子就是乙個容量為20的揹包,有乙個物品大小為5。那麼容量20的揹包就是dg[20],這個大小為5的東西,可以不裝,也可以裝。如果裝這個東西那麼dg[20]=dg[20-5]+5,不裝dg[20]不變,題目要求的是這兩個情況的最大值。

解釋一下,在裝入這個物品的情況下,那麼dg[20]就等於在揹包容量為15 (20-5)

的時候能裝的最大容量dg[15]與物品大小的和。不裝的話dg[20]不變。

如果你要在容量為20的揹包裡裝大小為5的東西,那麼揹包容量15時最多能放下的容量再加上這大小為5的東西,得出來的結果就是容量20下能裝的最大容量。

語文是真的不好,描述不清楚qaq

下面放三個例題來理一下這個思路

有乙個箱子容量為v(正整數,0<=v<=20000),同時有n個物品(0<n<=30),每個物品有乙個體積(正整數)。

要求n個物品中,任取若干個裝入箱內,使箱子的剩餘空間為最小。

輸入格式

第一行為乙個整數,表示箱子容量;

第二行為乙個整數,表示有n個物品;

接下來n行,每行乙個整數表示這n個物品的各自體積。

輸出格式

乙個整數,表示箱子剩餘空間。

樣例輸入246

83127

97樣例輸出

0這題要求裝完東西後箱子剩下的最小容量,換句話說就是箱子最大能裝多少東西。用一維陣列dg[i]標示箱子容量為i的情況下最多能放的容量。a[i]陣列表示每個物體的體積。

那麼dg[i]=max(dg[i],dg[i-v1]+v1)。

i-v1容量下的揹包能放的最多容量加上v1就是i容量能放的最大容量

或者就不放,兩個情況誰佔得容量大就要誰

**如下

#include

#include

using

namespace std;

intmain()

;int a[35]

=;int n;

int rl;

cin >> rl;

cin >> n;

for(

int i =

0; i < n; i++

) cin >> a[i]

;for

(int i =

0; i < n; i++)}

cout << rl-dp[rl]

<< endl;

return0;

}

**中的for(int j=rl;j>=a[i];j–)為什麼要倒著來,而不是for(int j=a[i];j<=rl;j++)呢

原因是如果一旦正著來,有些物品會被裝兩次

舉個例子

要放物品大小為5的東西

那麼容量從5開始到10(揹包容量)為止

dg[5]=5

dg[6]=5

dg[7]=5

dg[8]=5

dg[9]=5

dg[10]=dg[10-5]+5=10

上面可以看出來在容量為10的時候會求容量5能放的最多東西再加上5.

但是容量為5的揹包已經把這個東西放進去過,容量為10的時候就不能再用了

所以倒著來

dg[10]=dg[10-5]+5=5

dg[9]=5

dg[8]=5

…dg[5]=5

由於上來就計算容量10的揹包,那麼容量5的時候還是預設的0,所以dg[10]就等於5了(只放一次)

注意最後輸出的是剩下的容量,所以用揹包容量減去能放最多的東西來表示。

第二題辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到乙個到處都是草藥的山洞裡對他說:「孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採到一些草藥。如果你是乙個聰明的孩子,你應該可以讓採到的草藥的總價值最大。」

如果你是辰辰,你能完成這個任務嗎?

輸入格式

第一行有兩個整數t(1 <= t <= 1000)和m(1 <= m <= 100),用乙個空格隔開,t代表總共能夠用來採藥的時間,m代表山洞裡的草藥的數目。接下來的m行每行包括兩個在1到100之間(包括1和100)的整數,分別表示採摘某株草藥的時間和這株草藥的價值。

輸出格式

包括一行,這一行只包含乙個整數,表示在規定的時間內,可以採到的草藥的最大總價值。

樣例輸入

70 3

71 100

69 1

1 2樣例輸出

3資料規模和約定

對於30%的資料,m <= 10;

對於全部的資料,m <= 100。

題目怪長,看完其實還是01揹包,很好理解,總共能採藥的時間就是容量,在這個時間內,求採到的草藥的最大總價值

跟上面題目不一樣的地方就是,他求的不是容量了,而是價值,這也好辦,弄個二維陣列a[i][2]來存草藥的資料

i表示第幾個草藥,a[i][0]表示消耗的時間(占用容量),a[i][1]表示價值。

dg[j]表示在j時間內採取的最大草藥總價值

dg[j]=max(dg[j],dg[j-a[i][0]]+a[i][1])

在j-a[i][0]時間下的最大總價值加上a[i][1]就是j時間下的最大總價值

不管是求價值,還是求容量,思路都是不變的

#include

#include

using

namespace std;

intmain()

;int a[

105][2

]=;int t, m;

cin >> t >> m;

for(

int i =

0; i < m; i++

)for

(int i =

0; i < m; i++)}

cout << dg[t]

<< endl;

return0;

}

第三題

金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:「你的房間需要購買哪些物品,怎 麼布置,你說了算,只要不超過n元錢就行」。今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的n元。於是,他把每件物品規定了一 個重要度,分為5等:用整數1~5表示,第5等最重要。他還從網際網路上查到了每件物品的**(都是整數元)。他希望在不超過n元(可以等於n元)的前提 下,使每件物品的**與重要度的乘積的總和最大。

設第j件物品的**為v[j],重要度為w[j],共選中了k件物品,編號依次為 j1,j2,……,jk,則所求的總和為:

v[j1]*w[j1]+v[j2]*w[j2]+ …+v[jk]w[jk]。(其中為乘號)

請 你幫助金明設計乙個滿足要求的購物單。

輸入格式

輸入檔案 的第1行,為兩個正整數,用乙個空格隔開:

n m(其中n(<30000)表示總錢 數,m(<25)為希望購買物品的個數。)

從第2行到第m+1行,第j行給出了編號為j-1的物品的基本資料,每行有2個非負整數

v p(其中v表示該物品的**(v<=10000),p表示該物品的重要度(1~5))

輸出格式

輸出檔案只有乙個正整數,為不超過總錢數的物品的**與重要度乘積的總和的最大值(<100000000)。

樣例輸入

1000 5

800 2

400 5

300 5

400 3

200 2

樣例輸出

3900

又變了,而細心的同學發現了,變得又是要求的東西,實質還是01揹包。錢數就是容量,要求的東西變成了**和重要度的乘積和

這題跟第二題一樣,如果用第二題來套要求的就是草藥時間和價值的乘積和

那麼變數都一樣

dg[j]表示j錢數下取得的**和重要度的最大乘積和

a[i][0]表示第i個物品的**

a[i][1]則是重要度

dg[j]=max(dg[j-a[i][0]]+a[i][0]*a[i][1],dg[j])

#include

#include

using

namespace std;

intmain()

;int n, m;

int v, p;

int a[30]

[2]=

; cin >> n >> m;

for(

int i =

0; i < m; i++

)for

(int i =

0; i < m; i++)}

cout << dg[n]

<< endl;

return0;

}

在練過這幾道題後,對這一類問題的動態規劃思路已經熟悉了。以後再遇到這種題只要分析出是01揹包就可以快速解出來= - =

動態規劃揹包問題 01揹包

問題描述 n種物品,每種乙個。第i種物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包,使得揹包內物品不超過c的前提下,重量最大。問題分析 宣告乙個f n c 的陣列。f i j 表示把前i件物品都裝到容量為j的揹包所獲得的最大重量。當 j v i 時,揹包容量不足以放下第 i 件物品,f ...

動態規劃 揹包問題 01揹包

有n種物品和乙個容量為v的揹包,每種物品僅用一次。第i件物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使價值總和最大。例如 n 5,v 10 重量 價值 第乙個物品 10 5 第二個物品 1 4 第三個物品 2 3 第四個物品 3 2 第五個物品 4 1 首先我們考慮貪心策略,選取最大價...

0 1揹包問題(動態規劃)

一 問題描述 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。所謂01揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。二 解決方案 考慮使用動態規劃求解,定義乙個遞迴式 opt i v 表示前i個物品,在揹包容量大小為v的情況下,最...