ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

早上好,特工W-12,你需要完成的以下的任务。
我们已经渗透到一个叫混乱与祸害的组织中,希望能掌握该组织的管理权。不幸的是,它们似乎已经准备好应对这样的事件了,它们使用了一个很复杂的设计分配管理权力,这使得我们的渗透工作非常艰难。
那家组织的管理系统被分成若干个单位,对于任意两个单位A和B,要么A管理B要么B管理A,同时这个管理关系可以形成环,因此可以出现A管理B、B管理C、C管理A的情况。
我们可以安排特工去渗透到任意一个单位,那将使得我们控制该单位和那个单位直接管理的单位,但是不包括间接管理的单位。比如之前的样例,渗透到A单位会让我们控制A和B,但不能控制C。
对于一个成功的渗透工作来说,我们必须要控制所有的单位才行,否则其他单位会发现我们,同时破坏我们的计划。而你也知道,我们现在从更高的部门那里拿到的经费十分紧缺,我们必须最高效地完成任务。你的任务就是要找出控制单位最少的可行方案。

Input

第一行包含一个整数n,表示该组织的单位数。接下来n行每行n个二进制位。在其中的第i行第j列位置,若为1表示i单位控制j单位,否则j单位控制i单位

Output

共一行,第一个整数ans表示最少的控制单位数量
似乎没有正常的算法,所以用随机调整,随机排列1..n,顺序扫描删去可删的点,再随机加入一个点,重复多次
#include<cstdio>
#include<cstdlib>
#include<algorithm>
int n,ans;
char s[100][100];
int ps[100],pp=0;
int vs[100],stk[100],stp=0;
void cal(){
    stp=0;
    for(pp=0;pp<n;pp++)ps[pp]=pp,vs[pp]=0;
    for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(s[i][j])++vs[j];
    for(int t=0;t<5;t++){
        std::random_shuffle(ps,ps+pp);
        for(int i=0;i<pp;i++){
            int x=ps[i];
            bool ed=1;
            for(int j=0;j<n;j++)if(s[x][j]>=vs[j]){ed=0;break;}
            if(ed){
                for(int j=0;j<n;j++)if(s[x][j])--vs[j];
                stk[stp++]=x;
                ps[i--]=ps[--pp];
            }
        }
        if(pp<ans)ans=pp;
        if(!stp)continue;
        int w=rand()%stp;
        int x=ps[pp++]=stk[w];
        stk[w]=stk[stp--];
        for(int i=0;i<n;i++)if(s[x][i])++vs[i];
    }
}
int main(){
    srand(1844677);
    int T=1;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            scanf("%s",s[i]),s[i][i]='1';
            for(int j=0;j<n;j++)s[i][j]-='0';
        }
        ans=n;
        for(int i=0;i<180;i++)cal();
        printf("Case %d: %d\n",T,ans);
        T++;
    }
    return 0;
}

 

posted on 2016-06-28 08:56  nul  阅读(372)  评论(0编辑  收藏  举报