1. 程式人生 > >6006 Engineer Assignment——dp

6006 Engineer Assignment——dp

和揹包差不多

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
int T, n, m, c[maxn], d[maxn], a[maxn][maxn], b[maxn][maxn];
bool vis[maxn+10];
vector<int> vec[maxn];
int dp[15][(1<<10)+10];
int main() {
    scanf("%d", &T);
    for (int ks = 1; ks <= T; ks++) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) {
            scanf("%d", &c[i]);
            for (int j = 0; j < c[i]; j++) scanf("%d", &a[i][j]);
        }
        for (int i = 0; i < m; i++) {
            scanf("%d", &d[i]);
            for (int j = 0; j < d[i]; j++) scanf("%d", &b[i][j]);
        }
        for (int i = 0; i < n; i++) vec[i].clear();
        for (int i = 1; i < (1<<m); i++) {
            for (int j = 0; j <= 100; j++) vis[j] = 0;
            for (int j = 0; j < m; j++) if (i&(1<<j)) {
                for (int k = 0; k < d[j]; k++) vis[b[j][k]] = 1;
            }
            for (int j = 0; j < n; j++) {
                bool ok = true;
                for (int k = 0; k < c[j]; k++) if (!vis[a[j][k]]) { ok = false; break; }
                if (ok) vec[j].push_back(i);
            }
        }
        for (int i = 0; i <= n; i++) for (int j = 0; j < (1<<m); j++) dp[i][j] = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < (1<<m); j++) {
                dp[i][j] = dp[i-1][j];
                for (int k = 0; k < vec[i-1].size(); k++) {
                    if ((j|vec[i-1][k]) != j) continue;
                    dp[i][j] = max(dp[i][j], dp[i-1][j-vec[i-1][k]]+1);
                }
            }
        }
        printf("Case #%d: %d\n", ks, dp[n][(1<<m)-1]);
    }
    return 0;
}