揹包學習之揹包九講

2022-07-08 07:00:19 字數 3274 閱讀 5417

做了一些icpc題目,感受到動態規劃的重要性,在此學習揹包

參考至部落格揹包九講

問題:n個物品(體積和價值分別為v[i],w[i])和乙個體積為v的揹包,求揹包裝到的最大價值

狀態陣列:dp[i][j]為選前i個所用體積為j的最大價值

for(int i=1;i<=n;++i)

for(int j=1;j<=v;++j)

dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);

滾動陣列優化:

for(int i=1;i<=n;++i)

for(int j=v;j>=vi;--j)

dp[j]=max(dp[j],dp[j-v[i]])+w[i]

問題:n種物品(每種無限個,體積和價值分別為v[i],w[i])和乙個體積為v的揹包,求揹包最大價值

狀態陣列:dp[i][j]為選到前i種所用體積為j的最大價值

for(int i=1;i<=n;++i)

for(int j=0;j<=v;++j)

for(int k=1;k*v[i]<=j;++k)

dp[i][j]=max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]);

時間優化

for(int i=1;i<=n;++i)

for(int j=0;j<=v;++j)

滾動陣列空間優化

for(int i=1;i<=n;++i)

for(int j=v;j>=v[i];--j)

dp[j]=max(dp[j],dp[j-v[i]]+w[i]);

問題:n種物品(每種有限個,數量,體積和價值分別為s[i],v[i],w[i])和乙個體積為v的揹包,求揹包最大價值

狀態陣列:dp[i][j]為選到前i種所用體積為j的最大價值

for(int i=1;i<=n;++i)

for(int j=0;j<=v;++j)

for(int k=0;k*v[i]<=j&&k<=s[i];++k)

dp[i][j]=max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]);

空間優化

for(int i=1;i<=n;++i)

for(int j=v;j>=0;--j)

for(int k=0;k*v[i]<=j&&k<=s[i];++k)

dp[j]=max(dp[j],dp[j-k*v[i]]+k*w[i]);

二進位制時間優化

將數量為s[i]的物品分成s[i]=1+2+4+8+...+x,然後跑01揹包,複雜度由n3優化為n2logn

**略

問題:既有無限個的,又有單個的,又有多個的,仍然是揹包v,求最大價值

單個的可看成多重揹包的特殊狀況,然後有限個和無限個分別討論

直接上一維:dp[j]代表用j體積裝到的最大價值

for(int i=1;i<=n;++i) cin>>v[i]>>w[i]>>s[i];//當s[i]=0時,為無限個

for(int i=1;i<=n;++i)

else

if(!s[i]) continue;

for(int j=v;j>=s[i]*v[i];j--)

dp[j]=max(dp[j],dp[j-s[i]*v[i]]+s[i]*w[i]);

}}

問題:n個物品(體積,重量和價值分別為v[i],m[i],w[i])和乙個體積為v,限重為m的揹包,求揹包最大價值

問題:n種物品(每種有限個,數量,體積和價值分別為s[i],v[i],w[i])和乙個體積為v的揹包,求揹包最大價值

加一維就行了

狀態陣列:dp[i][j]代表體積為i,載重為j時的最大價值

for(int i=1;i<=n;++i)

for(int j=v;j>=v[i];j--)

for(int k=m;k>=m[i];--k)

dp[j][k]=max(dp[j][k],dp[j-v[i]][k-m[i]]+w[i]);

問題:n堆物品,每堆s[i]個,每個體積和價值為v[i],w[i],和乙個體積為v揹包,每堆物品只能選乙個,求最大價值

分組揹包看起來沒什麼用,實際上是各種dp題的熱門考點,特別是樹形dp

一維狀態:dp[j]代表用j體積的最大價值

for(int i=1;i<=n;++i)

for(int j=v;j>=0;--j)

for(int k=1;k<=s[i];++k)

if(j>=v[k])dp[j]=max(dp[j],dp[j-v[k]]+w[k]);

例題:p2014,2020icpc南京m

問題:n個物體之間存在著依賴關係,例如依賴關係是一棵樹,選擇乙個節點需要選擇其父親節點

實質上就是一道赤果果的樹形dp

狀態方程:dp[x][y] 代表x節點擊了體積為y的最大價值

void dfs(int s)

}

第二類問題:n節點數選m點,選乙個點必須選父節點,使總價值最大

狀態方程:dp[x][i] 代表x節點擊擇了i個節點的最大價值,答案就是dp[1][m]

void dfs(int s)

else if(dp[j-v[i]]+w[i]==dp[j])

num[j]+=num[j-v[i]];

}

問題:n個物品(體積和價值分別為v[i],w[i])和乙個體積為v的揹包,求選取價值達到最大的方案

for(int i=1;i<=n;++i)

for(int j=v;j>=vi;--j)

dp[j]=max(dp[j],dp[j-v[i]])+w[i];

int val=v;

for(int i=n;i>=1;--i)

if(val-v[i]>=0&&dp[val-v[i]]+w[i]==dp[val])

cout《如果題目有要求字典序最小,那求解01揹包的時候應當倒著求。

揹包九講之 01揹包

01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...

揹包九講之 完全揹包

完全揹包與01揹包的區別在於完全揹包第i件物品可以在允許範圍內選無數個,同樣的v i 表示體積,w i 表示價值。同樣的,我們先從二維入手,較為顯而易見。dp i j 表示前i件物品在容量為j的最大價值,那麼相應的也會出現很多情況 1.不選 dp i j dp i 1 j 2.選一件 dp i j ...

揹包九講 簡單揹包

揹包問題是一種動態規劃演算法的衍生問題。它可以被看作一種獨立的題型,也可以看作是一種線性動態規劃。學好揹包 學會揹包,對於深入理解動態規劃演算法有著極大的好處,並能幫助理解一些更深層次的動態規劃問題。那麼就開始吧 題目型別 有 n 件物品和乙個容量為 v 的揹包。第 i 件物品的費體積是 v i 價...