Description
Input
Output
Sample Input
4 10 4 5 3 6 1 2 100 200 1 2 1 2 330
Sample Output
333
Hint
Isun will buy Rubik 1 and Rubik 2, which make up family 1 and get 330 value increased. So they value 333 in all which is the largest value Isun can get with 10 RMB.
分组的dp,对于没有组的先直接01背包,然后同一组内的做一次01背包,把整个组当做一个物品做一次01背包,合起来就好了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int INF = 0x7FFFFFFF;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
int T, n, m, w[maxn], v[maxn], G[maxn], gg, f[maxn], vis[maxn], dp[maxn];
vector<int> g[maxn];
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = 0; i < n; i++) scanf("%d", &w[i]);
for (int i = 0; i < n; i++) scanf("%d", &v[i]);
for (int i = 0; i <= m; i++) f[i] = 0;
for (int i = 0; i < n; i++) vis[i] = 0;
scanf("%d", &gg);
for (int i = 0; i < gg; i++)
{
g[i].clear();
int x, y; scanf("%d", &x);
while (x--){ scanf("%d", &y), g[i].push_back(y - 1); vis[y - 1] = 1; }
scanf("%d", &G[i]);
}
for (int i = 0; i < n; i++)
{
if (vis[i]) continue;
for (int j = m; j >= w[i]; j--)
{
f[j] = max(f[j], f[j - w[i]] + v[i]);
}
}
for (int i = 0; i < gg; i++)
{
for (int j = 0; j <= m; j++) dp[j] = f[j];
int x = 0, y = G[i];
for (int j = 0; j < g[i].size(); j++)
{
x += w[g[i][j]]; y += v[g[i][j]];
for (int k = m; k >= w[g[i][j]]; k--)
{
dp[k] = max(dp[k], dp[k - w[g[i][j]]] + v[g[i][j]]);
}
}
for (int k = m; k >= x; k--) f[k] = max(f[k], f[k - x] + y);
for (int k = 0; k <= m; k++) f[k] = max(f[k], dp[k]);
}
printf("%d\n", f[m]);
}
return 0;
}