題目 多人揹包

2022-05-31 13:15:10 字數 1590 閱讀 5533

dd 和好朋友們要去爬山啦!他們一共有 k 個人,每個人都會背乙個包。這些包的容量是相同的,都是 v。可以裝進揹包裡的一共有 n 種物品,每種物品都有給定的體積和價值。

在 dd 看來,合理的揹包安排方案是這樣的:

每個人揹包裡裝的物品的總體積恰等於包的容量。

每個包裡的每種物品最多只有一件,但兩個不同的包中可以存在相同的物品。

任意兩個人,他們包裡的物品清單不能完全相同。

在滿足以上要求的前提下,所有包裡的所有物品的總價值最大是多少呢?

第一行有三個整數:k、v、n。(k<=50 v<=5000 n<=200 by rq)

第二行開始的 n 行,每行有兩個整數,分別代表這件物品的體積和價值。

只需輸出乙個整數,即在滿足以上要求的前提下所有物品的總價值的最大值。(最後有空行.)

題解:沒有做不到,只有想不到。

下面是摘自dd大牛的《揹包九講》:

求次優解、第k優解

對於求次優解、第k優解類的問題,如果相應的最優解問題能寫出狀態轉移方程、用動態規劃解決,那麼求次優解往往可以相同的複雜度解決,第k優解則比求最優解的複雜度上多乙個係數k。

其基本思想是將每個狀態都表示成有序佇列,將狀態轉移方程中的max/min轉化成有序佇列的合併。這裡仍然以01揹包為例講解一下。

首先看01揹包求最優解的狀態轉移方程:f[i][v]=max。如果要求第k優解,那麼狀態f[i][v]就應該是乙個大小為k的陣列f[i][v][1..k]。其中f[i][v][k]表示前i個物品、揹包大小為v時,第k優解的值。「f[i][v]是乙個大小為k的陣列」這一句,熟悉c語言的同學可能比較好理解,或者也可以

簡單地理解為在原來的方程中加了一維。顯然f[i][v][1..k]這k個數是由大到小排列的,所以我們把它認為是乙個有序佇列。

然後原方程就可以解釋為:f[i][v]這個有序佇列是由f[i-1][v]和f[i-1][v-c[i]]+w[i]這兩個有序佇列合併得到的。有序佇列f[i-1][v]即f[i-1][v][1..k],f[i-1][v-c[i]]+w[i]則理解為在f[i-1][v-c[i]][1..k]的每個數上加上w[i]後得到的有序佇列。合併這兩個有序佇列並將結果的前k項儲存到f[i][v][1..k]中的複雜度是o(k)。最後的答案是f[n][v][k]。總的複雜度是o(vnk)。

為什麼這個方法正確呢?實際上,乙個正確的狀態轉移方程的求解過程遍歷了所有可用的策略,也就覆蓋了問題的所有方案。只不過由於是求最優解,所以其它在任何乙個策略上達不到最優的方案都被忽略了。如果把每個狀態表示成乙個大小為k的陣列,並在這個陣列中有序的儲存該狀態可取到的前k個最優值。那麼,對於任兩個狀態的max運算等價於兩個由大到小的有序佇列的合併。

另外還要注意題目對於「第k優解」的定義,將策略不同但權值相同的兩個方案是看作同乙個解還是不同的解。如果是前者,則維護有序佇列時要保證佇列裡的數沒有重複的。

view code

1 #include

2using

namespace std;34

int f[5001][51],k,v,n,w[201],e[201];56

void jia(int a,int b,int p)

2021

int main()

22

多人揹包問題

爆了。而且是這種半年前刷過的題目。演算法是合併兩個有序的序列,其他的方程之類與單人揹包其實差不多。code include include include include define swap a,b,t define max a,b define min a,b define maxk 55 d...

動歸 多人揹包

求01揹包前k優解的價值和 輸入格式 第一行三個數k v n 接下來每行兩個數,表示體積和價值 輸出格式 前k優解的價值和 題解 這道題目是在01揹包的基礎上求出前k個最優解。dp i j 揹包容量為i,第j優解的值。由於任意兩個揹包不能完全相同,所以只初始化dp 0 1 0 因為要求必須恰好裝滿,...

Vijos P1412 多人揹包

p1412多人揹包 accepted 標籤 顯示標籤 dd 和好朋友們要去爬山啦!他們一共有 k 個人,每個人都會背乙個包。這些包的容量是相同的,都是 v。可以裝進揹包裡的一共有 n 種物品,每種物品都有給定的體積和價值。在 dd 看來,合理的揹包安排方案是這樣的 每個人揹包裡裝的物品的總體積恰等於...