今天我們要講有依賴揹包,揹包求方案數以及揹包求具體方案,咱們先來講有依賴揹包。
有依賴揹包是揹包家族中最難的,也是曾經勸退了無數人的題型。先給出題目和**把,如果這個揹包看不懂,那麼可以暫時跳過,因為這對於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。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第...第三講 多重揹包問題 對揹包九講的學習
動態規劃之揹包九講之三 多重揹包
動態規劃之揹包九講之四 混合揹包