就是一个背包问题,有多种物品,每种物品有价值和重量,个数无限,还有多个人,每个人可以拿的重量时一定的,并且每个人只能拿一种物品的一个,求这么多人取的最大价值是多少。
其实对于每一个人来说,就是一个01背包,但是我们不需要求多次,只需要求出来能拿重量最多的那个,那么少的自然就出来了,最后再加起来就行了。
代码如下:
/*************************************************************************
> File Name: 10130.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2014年12月19日 星期五 22时43分42秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
#define N 1010
struct Node {
int p, w;
int input(void)
{
return scanf("%d%d", &p, &w);
}
}node[N];
int g[N], dp[N];
int main(int argc, char *argv[])
{
int n, t, m;;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
node[i].input();
}
scanf("%d", &m);
for (int i = 0; i < m; ++i) {
scanf("%d", &g[i]);
}
clr(dp, 0);
for (int i = 0; i < n; ++i) {
for (int j = 30; j >= 0; --j) {
if (j - node[i].w >= 0 && dp[j] <= dp[j - node[i].w] + node[i].p) {
dp[j] = dp[j - node[i].w] + node[i].p;
}
}
}
int ans = 0;
for (int i = 0; i < m; ++i) {
ans += dp[g[i]];
}
printf("%d\n", ans);
}
return 0;
}