大二在讀生自己的總結,求大牛不要噴。。。
要做動態規劃題最重要的就是找思路,怎麼分解這個問題,把這個大問題化為小問題,小問題再化為更小的問題,最後就能做出來了。
動態規劃裡有乙個經典的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的情況下,最...