P1858 多人背包
Posted tony-double-sky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1858 多人背包相关的知识,希望对你有一定的参考价值。
P1858 多人背包
题目描述
求01背包前k优解的价值和
要求装满
调试日志: 初始化没有赋给 dp[0]
Solution
首先补充个知识点啊, 要求装满的背包需要初始赋 (-inf), 边界为 (dp[0] = 0)
第 (k) 优解的01背包
以 (dp[j][k]) 表示 容量为 (j) 的背包的第 (k) 优解
用到了归并排序的思想
对于第 (i) 个物品, 容量为 (j), 我们有两种选择:
- 选第 (i) 个物品
- 不选第 (i) 个物品
对于 (1-k) 中的每一个解做抉择, 我们可以得到 (2k) 种答案
由于答案分两边(选或不选)内部有序, 归并得到前 (k) 优即可
复杂度 (O(nmk))
Code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#define LL long long
#define REP(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
int out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
const int maxn = 10019;
int K, V, num;
int w[maxn], v[maxn];
int temp[maxn];
int dp[maxn][119];
int main(){
K = RD(), V = RD(), num = RD();
REP(i, 1, num)w[i] = RD(), v[i] = RD();
REP(i, 0, V)REP(k, 1, K)dp[i][k] = -1e9;
dp[0][1] = 0;
REP(i, 1, num){
for(int j = V;j >= w[i];j--){
int p1 = 1, p2 = 1, cnt = 0;
while(cnt <= K){
if(dp[j][p1] > dp[j - w[i]][p2] + v[i])temp[++cnt] = dp[j][p1++];
else temp[++cnt] = dp[j - w[i]][p2++] + v[i];
}
REP(k, 1, K)dp[j][k] = temp[k];
}
}
int ans = 0;
REP(i, 1, K)ans += dp[V][i];
printf("%d
", ans);
return 0;
}
以上是关于P1858 多人背包的主要内容,如果未能解决你的问题,请参考以下文章