hdu 4068 SanguoSHA

暴力题

选拔赛的题目当时想歪了也不敢下手做

题意:三国杀,我方和敌方都有n人,会给出我方武将的全部名字。然后下面n行,第i行先输入一个m,后面跟着m个名字,表示敌方第i个武将能克制我方的这m个武将,没有列出名字的武将则会克制敌方的第i个武将。两方对战,一方武将死了下一位补上,直到一方武将全部死亡则该方输掉了游戏。问你是否能构建出一种无敌的出场方式,无论敌方怎么派出武将,我方都必将取得胜利,如果不能输出No,能的话,输出Yes,另外如果有多种无敌序列,要按名字字典序输出(是指单个单个名字比较,而不是把全部名字压成一个字符串再比较)

由于数据规模很小n最大为6,所以其实是个水题,只要暴力枚举两方的全排列然后逐一比较即可

 

1.我方武将和敌方武将都从0到n-1标号。构建一个01矩阵g[i][j]=1,表示敌方的第i个武将能杀死我方的第i个武将,=0则表示不能杀死

2.枚举全排列用STL来写,但是注意用next_permutation()之前要先排序(或者你能保证一开始时是字典序最小序列),太久没用这个函数忘记排序WA了好几次

3.枚举全排列其实可以不用像代码中那样写,可以先把所有排列保存下来,以后直接用即可,可以节省时间,另外用dfs手打全排列也能提高时间,代码中为了方便就用STL

 

#include <cstdio>

#include <cstring>

#include <algorithm>

#define LEN 25

#define N 10

using namespace std;



bool g[N][N];

char name[N][LEN];

int n;

int p1[N],p2[N];



void change(int *ans)

{

    int x,y,OK=0;

    for(int i=0; i<n; i++)

    {

        x=ans[i];

        y=p1[i];

        if(strcmp(name[x],name[y]) < 0) 

            break;

        else if(strcmp(name[y],name[x]) < 0)

        {

            OK=1;

            break;

        }

    }

    if(OK)

        for(int i=0; i<n; i++)

            ans[i]=p1[i];

}



bool fight()

{

    int i=0,j=0,x,y;

    while(i<n && j<n)

    {

        x=p1[i];

        y=p2[j];

        if(g[y][x]) i++;

        else        j++;

    }

    return i<n;

}



void solve(int Case)

{

    for(int i=0; i<n; i++) p1[i]=p2[i]=i;



    int ans[N],FIND,OK;

    FIND=0;



    do

    {

        sort(p2,p2+n);

        OK=1;

        do

        {

            if(!fight())

            {

                OK=0;

                break;

            }

        }

        while(next_permutation(p2,p2+n)); 

       

        if(OK)

        {

            if(!FIND)

            {

                FIND=1;

                for(int i=0; i<n; i++) 

                    ans[i]=p1[i];

            }

            else 

                change(ans);

        }

    }

    while(next_permutation(p1,p1+n)); 



    if(!FIND)

        printf("Case %d: No\n",Case);

    else

    {

        printf("Case %d: Yes\n",Case);

        for(int i=0; i<n; i++)

        {

            if(i) printf(" ");

            printf("%s",name[ans[i]]);

        }

        printf("\n");

    }

}



void input()

{

    scanf("%d",&n);

    for(int i=0; i<n; i++) 

        scanf("%s",name[i]);

    memset(g,0,sizeof(g));

    for(int i=0; i<n; i++)

    {

        int m;

        char tmp[LEN];

        scanf("%d",&m);

        for(int j=0; j<m; j++)

        {

            scanf("%s",tmp);

            for(int k=0; k<n; k++) if(!strcmp(name[k],tmp))

            {

                g[i][k]=1;

                break;

            }

        }

    }

}



int main()

{

    int T,t;

    scanf("%d",&T);

    for(t=1; t<=T; t++)

    {

        input();

        solve(t);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)