洛谷P1858 多人揹包

2022-05-26 20:42:10 字數 1597 閱讀 7319

題目鏈結

dd 和好朋友們要去爬山啦!他們一共有 \(k\) 個人,每個人都會背乙個包。這些包的容量是相同的,都是 \(v\)。可以裝進揹包裡的一共有 \(n\) 種物品,每種物品都有給定的體積和價值。在 dd 看來,合理的揹包安排方案是這樣的:

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

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

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

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

第一行有三個整數:\(k\)、\(v\)、\(n\)。

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

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

2 10 5

3 12

7 20

2 45 6

1 1

57
總人數 \(k<=50\)。

每個揹包的容量 \(v<=5000\)。

物品種類數 \(n<=200\)。

其它正整數都不超過 5000。

輸入資料保證存在滿足要求的方案。

1s128m

remove!!!

多人揹包?那不就是揹包問題嗎?

看題目好像還是01揹包。

有\(k\)個人,每個人的揹包裝的東西不能相同,那麼不就是前\(k\)大01揹包嗎?

我們在原來的01揹包上增加一維來維護前\(k\)大就行了。

\(dp[i][j]\)表示體積為\(i\)時第\(j\)大的價值是多少。

轉移的時候要注意一下,要用類似於歸併排序合併時的方法轉移。(具體如何實現看**)

int u1=1,u2=1;

while(u1+u2-1<=k && (dp[j+a][u1]!=-1 || dp[j][u2]!=-1))

else

}for(int o=1;o<=u1+u2-2;o++)

dp[j+a][o]=us[o];//更新dp中的值

因為只求前\(k\)大的和,所以\(dp\)過程中只用維護前\(k\)大就行了。

注意最後更新時迴圈是1到\(u1+u2-2\),因為前面迴圈結束時\(u1\)或者\(u2\)會多加一次。

要注意這裡不能用1到\(k\),因為前\(k\)個可能不一定全部被更新過,如果\(dp[j+a][k]\)沒有被更新過,就用它去更新下乙個,就會出bug。

上**:

#includeusing namespace std;

int k,v,n;

int a,b;

int dp[5009][59];

int us[59];

int ans;

int main()else

}for(int o=1;o<=u1+u2-2;o++)

dp[j+a][o]=us[o];

}} }

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

ans+=dp[v][j];

printf("%d",ans);

return 0;

}

洛谷 P1858 多人揹包 DP

目錄輸入輸出樣例 說明思路 ac 洛谷 p1858 多人揹包 求01揹包前k優解的價值和 第一行三個數 k,v,n 接下來每行兩個數,表示體積和價值 前 k 優解的價值和 2 10 5 3 12 7 20 2 45 6 1 157對於100 的資料,k leq 50,v leq 5000,n leq...

P1858 多人揹包

求01揹包前k優解的價值和 輸入格式 第一行三個數k v n 接下來每行兩個數,表示體積和價值 輸出格式 前k優解的價值和 輸入樣例 1 2 10 5 3 12 7 20 2 45 6 1 1 輸出樣例 1 57 對於100 的資料,k 50,v 5000,n 200 solution 本題由於需要...

P1858 多人揹包

01揹包的前 k 優解 我們先考慮一下最平凡的01揹包問題是如何進行求解的,一維狀態下 f j max f j f j w i v i 有第k優解的限制怎麼辦,不妨加乙個維度,把動態規劃的轉移想象成圖中點與點之間 的移動 f j k 表示裝滿體積為 j 的揹包的第 k 優解 我們發現,最優解的數值是...