zoukankan      html  css  js  c++  java
  • Engineer Assignment(暴力+状压dp)

    题意:

    n个工程,m个研究员,每个工程需要Ci个领域(X1,X2..Xci)的研究员 ,每个研究员会Di个不同的领域(X1,X2..Xdi),要完成一个工程必须使得分配给这个工程的研究员覆盖了这个工程所需的所有领域。问如何分配研究员可以使能供完成的工程数最多?

    n,m<=10;Ci<=3;Di<=2;

    思路:

    由于n很小,可以枚举出一个工程分配的所有方案((2^{11}-1)),其中人员>3的方案可以舍弃(一定不是最优的)。将状态压缩为1~(2^{11}-1)的数,从第一个工程到第n个进行状压dp即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=20;
    int c[maxn],d[maxn];
    int a[maxn][10],b[maxn][10];
    int dp[maxn][1<<11];
    int vis[120];
    vector<int>V[maxn];
    int t,n,m;
    void init(){
        for(int i=1;i<=n;i++)
            V[i].clear();
        memset(dp,0,sizeof(dp));
    }
    int main(){
        cin>>t;
        for(int kase=1;kase<=t;kase++){
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=n;i++){
                scanf("%d",&c[i]);
                for(int j=1;j<=c[i];j++){
                    scanf("%d",&a[i][j]);
                }
            }
            for(int i=1;i<=m;i++){
                scanf("%d",&d[i]);
                for(int j=1;j<=d[i];j++){
                    scanf("%d",&b[i][j]);
                }
            }
            for(int i=1;i<=n;i++){
                for(int j=0;j<1<<m;j++){//枚举方案数
                    memset(vis,0,sizeof(vis));
                    int cnt=0;
                    for(int k=0;k<m;k++){//判断集合中有哪些人
                        if((1<<k)&j){//有id为k+1的人
                            for(int l=1;l<=d[k+1];l++){
                                vis[b[k+1][l]]=1;
                            }
                            cnt++;
                        }
                    }
                    if(cnt>3)continue;
                    int flag=1;
                    for(int k=1;k<=c[i];k++)
                        if(vis[a[i][k]]==0)
                            flag=0;
                    if(flag)V[i].push_back(j);
                }
            }
            for(int i=1;i<=n;i++){
                for(int j=0;j<1<<m;j++){
                    dp[i][j]=dp[i-1][j];
                    for(auto k:V[i]){
                        if((j|k)==j){//k属于j
                            dp[i][j]=max(dp[i-1][j-k]+1,dp[i][j]);
                        }
                    }
                }
            }
            printf("Case #%d: %d
    ",kase,dp[n][(1<<m)-1]);
        }
    }
    
  • 相关阅读:
    整合Sleuth
    idea springboot 微服务批量启动
    思维的八层境界(深度好文)
    【格局视野】三色需求与工作层次
    【阅读推荐】改变你思维模式的书单
    【软件架构】七款代码味道识别工具
    【软件架构】代码重构之道
    【Android】EventBus 源码解析
    【软件架构】IM架构设计(安卓版)
    【设计模式】Java版设计模式的类图汇总
  • 原文地址:https://www.cnblogs.com/ucprer/p/11728609.html
Copyright © 2011-2022 走看看