題目鏈結
dd 和好朋友們要去爬山啦!他們一共有 \(k\) 個人,每個人都會背乙個包。這些包的容量是相同的,都是 \(v\)。可以裝進揹包裡的一共有 \(n\) 種物品,每種物品都有給定的體積和價值。在 dd 看來,合理的揹包安排方案是這樣的:
每個人揹包裡裝的物品的總體積恰等於包的容量。
每個包裡的每種物品最多只有一件,但兩個不同的包中可以存在相同的物品。
任意兩個人,他們包裡的物品清單不能完全相同。
在滿足以上要求的前提下,所有包裡的所有物品的總價值最大是多少呢?
第一行有三個整數:\(k\)、\(v\)、\(n\)。
第二行開始的 \(n\) 行,每行有兩個整數,分別代表這件物品的體積和價值。
只需輸出乙個整數,即在滿足以上要求的前提下所有物品的總價值的最大值。
2 10 53 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 優解 我們發現,最優解的數值是...