通天之分组背包
题目背景
直达通天路·小 A 历险记第二篇
题目描述
自 01 01 01 背包问世之后,小 A 对此深感兴趣。一天,小 A 去远游,却发现他的背包不同于 01 01 01 背包,他的物品大致可分为 k k k 组,每组中的物品相互冲突,现在,他想知道最大的利用价值是多少。
输入格式
两个数 m , n m,n m,n,表示一共有 n n n 件物品,总重量为 m m m。
接下来 n n n 行,每行 3 3 3 个数 a i , b i , c i a_i,b_i,c_i ai,bi,ci,表示物品的重量,利用价值,所属组数。
输出格式
一个数,最大的利用价值。
样例 #1
样例输入 #1
45 3
10 10 1
10 5 1
50 400 2
样例输出 #1
10
提示
0
≤
m
≤
1000
0 \leq m \leq 1000
0≤m≤1000,
1
≤
n
≤
1000
1 \leq n \leq 1000
1≤n≤1000,
1
≤
k
≤
100
1\leq k\leq 100
1≤k≤100,
a
i
,
b
i
,
c
i
a_i, b_i, c_i
ai,bi,ci 在 int
范围内。
思路
分组背包是每组最多选一个,因此它又可以转化成01背包问题。
代码
#include<iostream>
using namespace std;
const int N = 1e7+10,M = 1e3+10;
int f[N];
int v[N],w[N],s[N];
int jl[M][M];
int n,V;
int num;
int main(){
cin>>V>>n;
for(int i=1;i<=n;i++){
int x;
cin>>v[i]>>w[i]>>x;
num=max(num,x);
s[x]++;//数量
jl[x][s[x]]=i;//第x组背包的第几种的物品的下标啊啊啊
}
for(int i=1;i<=num;i++){
for(int j=V;j>=0;j--){
for(int k=1;k<=s[i];k++){
int px=jl[i][k];
if(j>=v[px]){
f[j]=max(f[j],f[j-v[px]]+w[px]);
}
}
}
}
cout<<f[V];
return 0;
}