揹包問題總結

2022-04-29 19:57:12 字數 3281 閱讀 7899

有n件物品和乙個容量為v的揹包。第i件物品的費用是w[i],價值是v[i],求將哪些物品裝入揹包可使價值總和最大。

主要特徵:每個物品只有一件,只有放與不放兩種狀態,設dp[i][j]表示重量限制為j時在前i個物品中能得到的最大價值

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

\]因為每個物品只有兩種選擇則第i個不選,最大價值為dp[i-1][j],第i個要選時就要為第i個物品騰出w[i]的空間,再加上v[i];

可以發現前i個的狀態都是由前i-1個推來,則可以用滾動陣列滾動一維

一維情況第二層倒序列舉原因:因為是一維,正序列舉會把第i層更新的值覆蓋上去,而之後又傻乎乎把被覆蓋的值當做第i-1的值使用(其實也就是第i個物品可能被多次選用,完全揹包將要用到)

inline void _01beibao()

inline void _01kth()

for(rint cc=1;cc<=k;cc++) dp[j][cc]=gg[cc];

//這裡dp[j][k],表示第i層價值為j時的前k大值,顯然dp[i][v][1..k]這k個數是由大到小排列的,所以我們把它認為是乙個有序佇列。

//然後原方程就可以解釋為:dp[i][v]這個有序佇列是由dp[i-1][v]和dp[i-1][v-c[i]]+w[i]這兩個有序佇列合併得到的。}}

}

有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的費用是w[i],價值是v[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

基本特點:每個物品有無數件,狀態是取0-v/w[i]件。dp[i][j]定義同上,有

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

\]由於可以多次選取,正序列舉可以利用之前被w[i]更新的dp值(本質就是多次選擇),也因此可滾動一維。

inline void wanquanbeibao()

有nnn種物品和乙個容量為v的揹包。第i種物品最多有p[i]件可用,每件費用是w[i],價值是v[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

是完全揹包在個數上限制,多一層個數列舉,有

\[dp[i][j] = max(dp[i - 1][j - k \times w[i]] + k \times v[i]) (0 <= k <= num[i])

\]由於都是自上一層狀態轉移也可滾動一維

inline void duochongbeibao()

}

把p[i]件物品化為以2的冪次為單位的幾組,這幾組數字可以完全表示[1,p[i]]的所有整數(不能理解重學二進位制)複雜度從num降至log(num)

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

}

待更...

前三種揹包的三種不同性質的物品組合起來

inline void hunhebeibao()

} }

對於每件物品,具有兩種不同的費用;選擇這件物品必須同時付出這兩種代價;對於每種代價都有乙個可付出的最大值(揹包容量)。問怎樣選擇物品可以得到最大的價值。設這兩種代價分別為代價1和代價2,第i件物品所需的兩種代價分別為w[i]和g[i]。兩種代價可付出的最大值(兩種揹包容量)分別為v和t。物品的價值為v[i]。

只要再加一維就可以了,當每件物品只可以取一次時變數j和k採用逆序的迴圈,當物品有如完全揹包問題時採用順序的迴圈。當物品有如多重揹包問題時拆分物品。公式

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

\]

inline void erweibeibao()

有n件物品和乙個容量為v的揹包。第i件物品的費用是w[i],價值是v[i]。這些物品被劃分為若干組,每組中的物品互相衝突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

基本特點:每組中只選乙個物品或不選;定義dp[i][j]為前i組費用j時的最大價值,有

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

\]注意,第二,三層不能對調,否則可能會多次選擇同一物品(與01揹包的倒序原因類似)

inline void fenzubeibao()

這種揹包問題的物品間存在某種「依賴」的關係。也就是說,i依賴於j,表示若選物品i,則必須選物品j。為了簡化起見,我們先設沒有某個物品既依賴於別的物品,又被別的物品所依賴;另外,沒有某件物品同時依賴多件物品。

其它待更...dp[j]中j可表示「花費至多為j」或「花費剛好為j」,適應題目與處理方法也不同。有些要求能精確知道花費的題目就要把j設為後者。不同處理體現在「剛好」時的j不存在的情況對應的dp[j]也不應被採取,比如說求最大值時「至多」可以初始化dp為0,「恰好」初始化-inf防止被選為答案或用來更新

記錄下每個狀態的最優值是由狀態轉移方程的哪一項推出來的,換句話說,記錄下它是由哪乙個策略推出來的。便可根據這條策略找到上乙個狀態,從上乙個狀態接著向前推即可。還是以01揹包為例,方程為

f[i][j]=max(f[i−1][j],f[i−1][j−w[i]]+v[i])

再用乙個陣列g[i][j],設g[i][j]=0表示推出f[i][j]的值時是採用了方程的前一項(也即f[i][j]=f[i−1][j]),g[i][j]表示採用了方程的後一項。注意這兩項分別表示了兩種策略:未選第i個物品及選了第i個物品,最終狀態為f[n][v]。

另外,採用方程的前一項或後一項也可以在輸出方案的過程中根據f[i][j]的值實時地求出來,也即不須紀錄g陣列,將上述**中的g[i][j]0改成f[i][j]f[i−1][j],g[i][j]1改成f[i][j]f[i−1][j−w[i]]+v[i]也可。

字典序最小

ans記錄下後排序

一般只需將狀態轉移方程中的max改成sum即可。例如若每件物品均是完全揹包中的物品,轉移方程即為

\[dp[i][j] = σdp[i−1][j],dp[i][j−w[i]]

\]初始條件f[0][0]=1。事實上,這樣做可行的原因在於狀態轉移方程已經考察了所有可能的揹包組成方案。

感謝並推薦部落格1

部落格2與揹包九講原文

乾脆揹包九講.pdf

揹包問題 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件裡面挑選一些放到乙個容量一定的揹包裡面,使得你的揹包裡的東西總價值最大。對於這些東西的每一件,你可以選擇放進你...