揹包問題總結

2021-08-28 16:41:54 字數 1874 閱讀 3668

打了一盤模擬賽,發現自己把揹包忘得差不多了,特於此總結並備忘ps

ps:每種模型分別給出基礎版和滾動陣列版,前者用於理解,後者用於記憶和運用

1. 01揹包

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

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

if(j>=v[i])

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

else

dp[i][j]=dp[i-1][j];

滾動陣列(從後往前推,防止覆蓋)

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

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

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

2. 多重揹包

(注意k從0開始)

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

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

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

if(j>=v[i]*k)

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

else

dp[i][j]=dp[i-1][j];

滾動陣列(k從1開始)

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

for(int j=m;j>=1;j--)

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

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

超時,考慮離散化優化:

int x,y,z,t=1;

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

v[++n1]=x*s;

w[n1]=y*s;

}

然後按01揹包寫,注意離散後v陣列大小變成了n1

或者使用另一種技巧(較複雜,不建議)

cin>>n>>v;

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

if(m*w=w0[i];j--)

if(dp[j]3. 完全揹包

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

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

if(j>=v[i])

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

else

dp[i][j]=dp[i-1][j];

滾動陣列

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

for(int j=v[i];j<=m;j++)

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

此類問題大多數恰好裝滿揹包

這裡給出具有代表性的完全揹包類,其他的都差不多,很容易舉一反三

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

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

if(j>=v[i])

dp[i][j]=dp[i-1][j]+dp[i][j-v[i]];

else

dp[i][j]=dp[i-1][j];

滾動陣列

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

for(int j=v[i];j<=m;j++)

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

待更新......

揹包問題 01揹包總結

寫這篇部落格的原因是因為自己初學揹包的時候覺得好玄學。只是知道怎麼寫,但是具體是為什麼覺得很玄妙。在此其實希望和我一樣的小白萌新早點明白其中的原理,其實原理很簡單,只要懂了這個圖,我想01揹包就不成問題了。首先要明確這張表是至底向上,從左到右生成的。關於01揹包的題目暫時整理了一點。1.簡單01揹包...

揹包問題總結

標籤 acm dp 揹包 n 物品,乙個揹包,每個物品價值wi 體積vi 揹包容量 c 求最大價值 對於物品 i可選可不選 fi j fi 1 j vi j 0 fi j max c j vi 給定 n 種物品和乙個揹包。第 i種物品的價值是 wi 其體積為vi 揹包的容量為 c 同一種物品的數量無...

揹包問題總結

揹包問題主要是分為三種 0 1揹包,完全揹包,多重揹包 1 0 1揹包 定義 何謂0 1揹包,可以這樣想,那裡有一堆值錢的東西,每一樣東西只有一件,他們的價值和體積都不一樣,現在要你從這n件裡面挑選一些放到乙個容量一定的揹包裡面,使得你的揹包裡的東西總價值最大。對於這些東西的每一件,你可以選擇放進你...