分组背包
大概题意
给你n种预算,每个预算包含d组方案以及总预算B,每一个方案中都有4对治病策略(即花费多少钱能治多少病人),而且一定要达到策略中的预算才能治疗对应数量的病人,否则只能治疗前一策略(预算更少的策略)能治疗的病人数量。求用给定的总预算能够治疗的最多病人数。
思路:
该题为01背包的变形——分组背包问题
01背包:有n种物品,有一个容量为m的背包,每种可选可不选,求背包所能放的最大价值;
for(int i = 1; i <= 4; i++){
for(int j = m; j >= v[i]; j--){
f[j] = max(f[j], f[j-v[i]]+w[i]);
}
}
分组背包:有n组物品,每组4种,有一个容量为m的背包,每组物品中最多选一个,求背包所能放的最大价值;
区别:每一组中有不同的物品,体积,价值不固定,在枚举物品时,加一层循环,枚举组里的所有物品。
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
for(int k=1;k<=4;k++){
if(j>=v[k]) f[j]=max(f[j], f[j-v[k]]+w[k]);
}
因此,本题的最终代码如下:
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 100010;
int f[maxn], v[maxn], w[maxn];
int main(){
int t;
scanf("%d", &t);
for(int i = 1; i <= t; i++){
int n, m;
scanf("%d%d", &n, &m);
memset(f, 0, sizeof f);
for(int j = 1; j <= n; j++){
for(int k = 1; k <= 4; k++){
scanf("%d%d", &v[k], &w[k]);
}for(int s = m; s >= 0; s--){
for(int k = 1; k <= 4; k++){
if(s >= v[k])
f[s] = max(f[s], f[s - v[k]] + w[k]);
}
}
}
printf("Budget #%d: Maximum of %d lives saved.\n\n", i, f[m]);
}
}