動態規劃入門篇 揹包九講 (最後三講)

2021-09-28 17:01:12 字數 3303 閱讀 5408

今天我們要講有依賴揹包,揹包求方案數以及揹包求具體方案,咱們先來講有依賴揹包。

有依賴揹包是揹包家族中最難的,也是曾經勸退了無數人的題型。先給出題目和**把,如果這個揹包看不懂,那麼可以暫時跳過,因為這對於dp的入門者來說有些難度:

有 n 個物品和乙個容量是 v 的揹包。

物品之間具有依賴關係,且依賴關係組成一棵樹的形狀。如果選擇乙個物品,則必須選擇它的父節點。

如下圖所示:

如果選擇物品5,則必須選擇物品1和2。這是因為2是5的父節點,1是2的父節點。

每件物品的編號是 i,體積是 vi,價值是 wi,依賴的父節點編號是 pi。物品的下標範圍是 1…n。

求解將哪些物品裝入揹包,可使物品總體積不超過揹包容量,且總價值最大。

輸出最大價值。

輸入格式

第一行有兩個整數 n,v,用空格隔開,分別表示物品個數和揹包容量。

接下來有 n 行資料,每行資料表示乙個物品。

第 i 行有三個整數 vi,wi,pi,用空格隔開,分別表示物品的體積、價值和依賴的物品編號。

如果 pi=−1,表示根節點。 資料保證所有物品構成一棵樹。

輸出格式

輸出乙個整數,表示最大價值。

資料範圍

1≤n,v≤100

1≤vi,wi≤100

父節點編號範圍:

內部結點:1≤pi≤n;

根節點 pi=−1;

先給出**:

#include

#include

#include

using

namespace std;

const

int n=

110;

vector<

int> ver[n]

;int n,v;

int f[n]

[n];

int c[n]

,w[n]

;void

dfs(

int p)

for(

int i=v;i>=c[p]

;i--

) f[p]

[i]=f[p]

[i-c[p]

]+w[p]

;for

(int i=

0;i;i++

) f[p]

[i]=0;

}int

main()

ver[p]

.push_back

(i);

}dfs

(root)

; cout<[v]

}

這道題可以說是對前面所有揹包的總結,是揹包問題的精華。揹包問題不變法則:先迴圈物品,再迴圈體積(重量),最後迴圈決策,這也是動態規劃問題的核心思想。首先這個問題先轉化為分組揹包,我們將每個子揹包當成乙個整體,這就形成了分組揹包。我們用dfs列舉所有子樹,把子樹當成是乙個整體,鄰接表迴圈物體,然後迴圈體積(01揹包的方式,從大到小),然後暴力列舉每組裡面的所有決策(所有體積)。有一點比較特殊就是,根節點必須選,如果你能選那就強制你選,如果不能選不好意思,那就置零。**比較簡單,但一定要理清思路。如果你搞懂了這題,恭喜你下面兩題你也會不費吹灰之力的拿下,你成功的踏出了征服dp的第一步,也是你征服dp最堅實的後盾。

下面兩題太簡單了沒什麼好講的,我多寫點注釋自己感受吧

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。

第 i 件物品的體積是 vi,價值是 wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。

輸出 最優選法的方案數。注意答案可能很大,請輸出答案模 109+7 的結果。

輸入格式

第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。

接下來有 n 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。

輸出格式

輸出乙個整數,表示 方案數 模 109+7 的結果。

資料範圍

0#include

#include

#include

using

namespace std;

const

int inf=

100000000

;const

int n=

1010

;const

int mod=

1e9+7;

int f[n]

;//價值

int g[n]

;//方案數

intmain()

}int max=

-inf;

for(

int i=

0;i<=v;i++

) max=

max(f[i]

,max)

;int res=0;

for(

int i=

0;i<=v;i++

) cout

}有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。

第 i 件物品的體積是 vi,價值是 wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。

輸出 字典序最小的方案。這裡的字典序是指:所選物品的編號所構成的序列。物品的編號範圍是 1…n。

輸入格式

第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。

接下來有 n 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。

輸出格式

輸出一行,包含若干個用空格隔開的整數,表示最優解中所選物品的編號序列,且該編號序列的字典序最小。

物品編號範圍是 1…n。

資料範圍

0#include

#include

#include

using

namespace std;

const

int n=

1010

;int f[n]

[n];

int c[n]

,w[n]

;int

main()

for(

int i=n;i>=

1;i--

)//將狀態累次到第乙個物品,然後再模擬選擇的過程就能得到字典序最小的結果了

}int vol=v;

//最後模擬一下狀態就好了

for(

int i=

1;i<=n;i++)if

(vol<0)

break;}

return0;

}

第三講 多重揹包問題 對揹包九講的學習

有n種物品和乙個容量為v的揹包。第i種物品最多有n i 件可用,每件費用是c i 價值是w i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。對每個物品都考慮拿幾個 這個很好理解 遞推式 f i v max 時間複雜度是o v n i 這裡利用了二進位制的性質優化 時間...

動態規劃之揹包九講之三 多重揹包

題目 有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數...

動態規劃之揹包九講之四 混合揹包

題目 有 n 種物品和乙個容量是 v 的揹包。物品一共有三類 第一類物品只能用1次 01揹包 第二類物品可以用無限次 完全揹包 第三類物品最多只能用 si 次 多重揹包 每種體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第...