多人背包
题目描述
求01背包前k优解的价值和
DD 和好朋友们要去爬山啦!
他们一共有 K 个人,每个人都会背一个包。这些包 的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有 给定的体积和价值。
在 DD 看来,合理的背包安排方案是这样的: 每个人背包里装的物品的总体积恰等于包的容量。 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。
任意两个人,他们包里的物品清单不能完全相同。 在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?
输入格式
第一行三个数K、V、N
接下来每行两个数,表示体积和价值
输出格式
前k优解的价值和
样例 #1
样例输入 #1
2 10 5
3 12
7 20
2 4
5 6
1 1
样例输出 #1
57
提示
对于100%的数据, K ≤ 50 , V ≤ 5000 , N ≤ 200 K\le 50,V\le 5000,N\le 200 K≤50,V≤5000,N≤200
学到了新的技巧:刷表
貌似 dp 都可以求次优解和第 k k k 优解了?
/*
A: 10min
B: 20min
C: 30min
D: 40min
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <assert.h>
#include <sstream>
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
// #pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
template<typename T>inline void rd(T &a) {
char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}
typedef pair<long long ,long long >PII;
typedef pair<long,long>PLL;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+10,M=1e9+7;
// 重写max函数
template<typename T>
inline T Max(T a,T b){
return a>b?a:b;
}
int k,n,m;
int f[5010][55]; // f[i][j][k] 表示从前 i-1 个物品中选择体积为恰好为j的所有方案的第k优解的值
int que[5010];
void solve(){
cin>>k>>m>>n;
memset(f,-0x3f,sizeof f);
f[0][1] = 0;
fo(i,1,n){
int v,w;cin>>v>>w;
for(int j=m;j>=v;j--){
int c1,c2,cnt=0;
c1=c2=1;
while(cnt<k){
if(f[j][c1]>f[j-v][c2]+w){
que[++cnt]=f[j][c1++];
}
else{
que[++cnt]=f[j-v][c2++]+w;
}
}
for(int c=1;c<=k;c++){
f[j][c]=que[c];
}
}
}
int ans=0;
fo(i,1,k){
ans+=f[m][i];
}
cout<<ans<<endl;
}
int main(){
solve();
return 0;
}