码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 6006 Engineer Assignment:状压dp

时间:2017-08-15 10:20:06      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:cin   enc   vector   lan   false   std   cas   seq   sign   

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6006

题意:

  在Google中,有个n项目,m个专家。第i个项目涉及c[i]个领域,分别为a[i][0]...a[i][c[i]-1]。第i个专家精通d[i]个领域,分别为b[i][0]...b[i][d[i]-1]。

  如果要完成一个项目,则这个项目所涉及到的每一个领域都必须至少有一个精通该领域的专家。你作为director,可以任意分配专家,但一个专家只能去做一个项目。问你最多能够完成多少个项目。

 

题解:

  首先表示状态:

    当前考虑到第i个项目,专家的状态为state(每一位上0表示还没选,1表示已经选过了),在这之前最多能完成dp个项目。

    即:dp[i][state] = max num of finished pros

  如何转移:

    对于第i个项目,可以做或不做。

    (1)如果不做,则专家的状态state没有变化。

      dp[i+1][state] = max(dp[i+1][state], dp[i][state])

    (2)如果做,则首先要满足在剩下的专家中,有一些人能够完全覆盖到这个项目所涉及的领域。设这个项目可以选择的专家的方案为nex(每一位0代表不选,1代表选)。那么转移为:

      if(!(state&nex)) dp[i+1][state|nex] = max(dp[i+1][state|nex], dp[i][state] + 1)


  Tips:先预处理出每个项目合法的选专家的方案,存到vector中。

  求dp:先枚举第i个项目,再枚举此时的状态,做或不做两种情况分别处理。

 

AC Code:

  1 // dp[i][state] = max num of finished pros
  2 // dp[i+1][state|nex] = max self and dp[i][state] + 1
  3 // preprocess: the sequence of selected experts for each pros
  4 // a state on exps is legal only if state_exp & state_now == 0
  5 
  6 #include <iostream>
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <vector>
 10 #define MAX_N 15
 11 #define MAX_C 5
 12 #define MAX_A 105
 13 #define MAX_S (1<<12)
 14 
 15 using namespace std;
 16 
 17 int n,m,t;
 18 int cas=0;
 19 int ans;
 20 int a[MAX_N][MAX_C];
 21 int b[MAX_N][MAX_C];
 22 int c[MAX_N];
 23 int d[MAX_N];
 24 bool pro[MAX_N][MAX_A];
 25 bool exp[MAX_N][MAX_A];
 26 int dp[MAX_N][MAX_S];
 27 vector<int> transfer[MAX_N];
 28 
 29 void read()
 30 {
 31     memset(pro,false,sizeof(pro));
 32     memset(exp,false,sizeof(exp));
 33     cin>>n>>m;
 34     for(int i=0;i<n;i++)
 35     {
 36         cin>>c[i];
 37         for(int j=0;j<c[i];j++)
 38         {
 39             cin>>a[i][j];
 40             pro[i][a[i][j]]=true;
 41         }
 42     }
 43     for(int i=0;i<m;i++)
 44     {
 45         cin>>d[i];
 46         for(int j=0;j<d[i];j++)
 47         {
 48             cin>>b[i][j];
 49             exp[i][b[i][j]]=true;
 50         }
 51     }
 52 }
 53 
 54 bool check(int k,int state)
 55 {
 56     for(int i=0;i<c[k];i++)
 57     {
 58         int ned=a[k][i];
 59         bool flag=false;
 60         for(int j=0;j<m;j++)
 61         {
 62             if(((state>>j)&1) && exp[j][ned])
 63             {
 64                 flag=true;
 65                 break;
 66             }
 67         }
 68         if(!flag) return false;
 69     }
 70     return true;
 71 }
 72 
 73 void cal_exp()
 74 {
 75     for(int i=0;i<n;i++)
 76     {
 77         transfer[i].clear();
 78         for(int state=0;state<(1<<m);state++)
 79         {
 80             if(check(i,state)) transfer[i].push_back(state);
 81         }
 82     }
 83 }
 84 
 85 void cal_dp()
 86 {
 87     memset(dp,0,sizeof(dp));
 88     ans=0;
 89     for(int i=0;i<n;i++)
 90     {
 91         for(int state=0;state<(1<<m);state++)
 92         {
 93             dp[i+1][state]=max(dp[i+1][state],dp[i][state]);
 94             for(int j=0;j<transfer[i].size();j++)
 95             {
 96                 int nex=transfer[i][j];
 97                 if(!(state&nex))
 98                 {
 99                     dp[i+1][state|nex]=max(dp[i+1][state|nex],dp[i][state]+1);
100                 }
101             }
102         }
103     }
104 }
105 
106 void solve()
107 {
108     cal_exp();
109     cal_dp();
110     for(int state=0;state<(1<<m);state++)
111     {
112         ans=max(ans,dp[n][state]);
113     }
114 }
115 
116 void print()
117 {
118     cout<<"Case #"<<(++cas)<<": "<<ans<<endl;
119 }
120 
121 int main()
122 {
123     cin>>t;
124     while(t--)
125     {
126         read();
127         solve();
128         print();
129     }
130 }

 

HDU 6006 Engineer Assignment:状压dp

标签:cin   enc   vector   lan   false   std   cas   seq   sign   

原文地址:http://www.cnblogs.com/Leohh/p/7362354.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!