题意:n个工作,m个人完成,每个工作有ci个阶段,一个人只能选择一种工作完成,可以不选,且只能完成该工作中与自身标号相同的工作阶段,问最多能完成几种工作。
分析:
1、如果一个工作中的某个工作阶段没有任何一个人能完成,则这个工作是不可完成的。
2、预处理每个人能完成各工作的各工作阶段。
3、剪枝:如果当前完成工作数+剩余人数<=ans则剪枝。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const int MAXN = 10 + 10; const int MAXT = 10000 + 10; using namespace std; vector<int> t[MAXN], project[MAXN]; vector<int> engineer[MAXN]; int status[MAXN]; int work[MAXN][MAXN]; int ans; int n, m; map<int, int> mp; int projectnum; void dfs(int cur, int done){ if(done + m - (cur - 1) <= ans) return; if(cur == m + 1){ ans = max(ans, done); return; } dfs(cur + 1, done); for(int i = 1; i <= projectnum; ++i){ int len = project[i].size(); if(status[i] == (1 << len) - 1) continue; int tmp = status[i]; status[i] |= work[cur][i]; if(status[i] == (1 << len) - 1){ dfs(cur + 1, done + 1); } else{ dfs(cur + 1, done); } status[i] = tmp; } } void have(int x, int y){ int len1 = engineer[x].size(); int len2 = project[y].size(); for(int i = 0; i < len2; ++i){ bool ok = false; for(int j = 0; j < len1; ++j){ if(engineer[x][j] == project[y][i]){ ok = true; break; } } if(ok) work[x][y] |= (1 << i); } } int main(){ int T; scanf("%d", &T); int kase = 0; while(T--){ mp.clear(); ans = 0; for(int i = 0; i < MAXN; ++i){ project[i].clear(); engineer[i].clear(); t[i].clear(); } memset(work, 0, sizeof work); memset(status, 0, sizeof status); scanf("%d%d", &n, &m); int k, x; for(int i = 1; i <= n; ++i){ scanf("%d", &k); for(int j = 0; j < k; ++j){ scanf("%d", &x); t[i].push_back(x); } } for(int i = 1; i <= m; ++i){ scanf("%d", &k); for(int j = 0; j < k; ++j){ scanf("%d", &x); mp[x] = 1; engineer[i].push_back(x); } } projectnum = 0; for(int i = 1; i <= n; ++i){ int l = t[i].size(); bool ok = true; for(int j = 0; j < l; ++j){ if(!mp.count(t[i][j])){ ok = false; break; } } if(ok) project[++projectnum] = t[i]; } for(int i = 1; i <= m; ++i){ for(int j = 1; j <= projectnum; ++j){ have(i, j); } } dfs(1, 0); printf("Case #%d: %d ", ++kase, ans); } return 0; }