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;
}
原文地址:https://www.cnblogs.com/scau20110726/p/2954016.html