1. 程式人生 > >Engineer Assignment HDU

Engineer Assignment HDU

題目大意: 有n個任務,每個任務有一些要求,有m個人,每個人可以解決一些要求,問你,最多可以完成多少任務。 分析: 由於n和m很小,我們可以考慮狀壓DP,首先,預處理出來每個任務所需的人數組合,然後進行dp dp[i][j]=max(dp[i-1][j-t[i][k]]+1,dp[i][j]); dp[i][j]=max(dp[i][j],dp[i-1][j]);

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set> #include <map> using namespace std; const int maxn = 10 + 10; vector<int>a[maxn],b[maxn],t[maxn]; int n,m; int vis[110]; int dp[maxn][2000]; void init() { for(int i=0;i<maxn;i++) { a[i].clear(); b[i].clear(); t[i].clear(); } memset(vis,0,sizeof(vis)
); memset(dp,0,sizeof(dp)); } void solve() { for(int i=1;i<=n;i++) { for(int j=0;j<(1<<m);j++) { for(int l=0;l<a[i].size();l++) vis[a[i][l]]=0; int tot=0; for(int k=1;k<=m;k++) { if
(j&(1<<(k-1))) { tot++; for(int l=0;l<b[k].size();l++) { // if(j==12) cout<<b[k][l]<<"***"<<endl; vis[b[k][l]]=1; } } } if(tot>3) continue; int cnt=0; for(int l=0;l<a[i].size();l++) { // if(j==12) // cout<<vis[a[i][l]]<<"..."<<endl; if(vis[a[i][l]]) cnt++; } if(cnt==a[i].size()) { t[i].push_back(j); } } } // for(int i=1;i<=n;i++) // { // cout<<i<<" "; // for(int j=0;j<t[i].size();j++) // { // cout<<t[i][j]<<" "; // } // cout<<endl; // } } void solve1(int kase) { for(int i=1;i<=n;i++) { for(int j=0;j<(1<<m);j++) { for(int k=0;k<t[i].size();k++) { if((j|t[i][k])==j) dp[i][j]=max(dp[i-1][j-t[i][k]]+1,dp[i][j]); } dp[i][j]=max(dp[i][j],dp[i-1][j]); } } printf("Case #%d: %d\n",kase,dp[n][(1<<m)-1]); } int main() { int T,x,y; scanf("%d",&T); for(int kase=1;kase<=T;kase++) { init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&x); while(x--) { scanf("%d",&y); a[i].push_back(y); } } for(int i=1;i<=m;i++) { scanf("%d",&x); while(x--) { scanf("%d",&y); b[i].push_back(y); } } solve(); solve1(kase); } return 0; }