• HDU 6006 Engineer Assignment:状压dp


    题目链接: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 }
  • 相关阅读:
    [hdu4631 Sad Love Story]最近点对,枚举
    [hdu4629 Burning]三角形面积并,扫描线
    [hdu4628 Pieces]二进制子状态,DP
    [hdu4627 The Unsolvable Problem]数论
    [hdu4622 Reincarnation]后缀数组
    [hdu5379 Mahjong tree]dfs计数
    [hdu5375 Gray code]DP
    决策树
    算法题解之位运算
    算法题解之滑动窗口
  • 原文地址:https://www.cnblogs.com/Leohh/p/7362354.html
Copyright © 2020-2023  润新知