目录
题意:一共有n个任务,完成某个任务需要会一些领域的人,一共有m个工程师,每个工程师会一些领域,问这些工程师最多完成多少任务。
析:一个简单的状压DP,在比赛,算着时间复杂度过不了,结果才15ms,说一下思路,先预处理每个工程能有哪几种工程师来完成,然后dp[i][s] 表示前 i 个任务,工程师状态为要来完成的最多几个工程,dp[i][s] = max { dp[j][s^x] + 1 }。其中 x 是完成 i 工程所以需要的工程师。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <cmath> #include <stack> #include <sstream> #include <list> #include <assert.h> #include <bitset> #define debug() puts("++++"); #define gcd(a, b) __gcd(a, b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a, b, sizeof a) #define sz size() #define pu push_up #define pd push_down //#define mp make_pair #define cl clear() //#define all 1,n,1 #define FOR(x,n) for(int i = (x); i < (n); ++i) #define freopenr freopen("in.txt", "r", stdin) #define freopenw freopen("out.txt", "w", stdout) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair< int , int > P; const int INF = 0x3f3f3f3f; const LL LNF = 1e18; const double inf = 1e20; const double PI = acos (-1.0); const double eps = 1e-8; const int maxn = 1e5 + 100; const LL mod = 1e9 + 7; const int dr[] = {-1, 0, 1, 0}; const int dc[] = {0, 1, 0, -1}; const char *de[] = { "0000" , "0001" , "0010" , "0011" , "0100" , "0101" , "0110" , "0111" , "1000" , "1001" , "1010" , "1011" , "1100" , "1101" , "1110" , "1111" }; int n, m; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; inline bool is_in( int r, int c) { return r > 0 && r <= n && c > 0 && c <= m; } int dp[15][1500]; int pst[20], est[20]; int plen[20], elen[20]; int cnt; map< int , int > mp; int ID( int x){ if (mp.count(x)) return mp[x]; return mp[x] = cnt++; } vector< int > v[15]; int main(){ int T; cin >> T; for ( int kase = 1; kase <= T; ++kase){ scanf ( "%d %d" , &n, &m); mp.cl ; cnt = 0; for ( int i = 0; i < n; ++i){ scanf ( "%d" , &plen[i]); pst[i] = 0; for ( int j = 0; j < plen[i]; ++j){ int y; scanf ( "%d" , &y); pst[i] |= 1<<ID(y); } } for ( int i = 0; i < m; ++i){ scanf ( "%d" , &elen[i]); est[i] = 0; for ( int j = 0; j < elen[i]; ++j){ int y; scanf ( "%d" , &y); if (mp.count(y)) est[i] |= 1<<mp[y]; } } for ( int i = 0; i < n; ++i){ int st = 0; v[i].cl; for ( int j = 0; j < m; ++j) if ((pst[i] & est[j]) == pst[i]) v[i].pb(1<<j); if (plen[i] > 1){ for ( int j = 0; j < m; ++j) for ( int k = j+1; k < m; ++k) if ((pst[i] & (est[j]|est[k])) == pst[i]) v[i].pb(1<<j|1<<k); } if (plen[i] > 2){ for ( int j = 0; j < m; ++j) for ( int k = j+1; k < m; ++k) for ( int l = k+1; l < m; ++l) if ((pst[i] & (est[j]|est[k]|est[l])) == pst[i]) v[i].pb(1<<j|1<<k|1<<l); } } ms(dp, 0); int ans = 0; for ( int i = 0; i < v[0].sz; ++i){ dp[0][v[0][i]] = 1; ans = max(ans, dp[0][v[0][i]]); } int all = 1<<m; for ( int i = 1; i < n; ++i){ for ( int j = 1; j < all; ++j){ for ( int k = 0; k < v[i].sz; ++k){ if ((v[i][k]&j) != v[i][k]) continue ; for ( int l = 0; l < i; ++l) dp[i][j] = max(dp[i][j], dp[l][j^v[i][k]]+1); ans = max(ans, dp[i][j]); } } } printf ( "Case #%d: %d\n" , kase, ans); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步