CTU Open Contest 2016 H. It's Raining, Man 模拟 分类讨论

来源:互联网 发布:tcp和udp的默认端口 编辑:程序博客网 时间:2024/05/21 08:09

Walter is spending holidays at the farm of his great-grandfather. It is raining and raining and raining. Walter sits in the attic of an aged barn where he has found a pack of old poker cards among piles of various dusty junk. The cards look quite antiquated and interesting. He starts to lay down the cards one by one, side by side, on the floor when he suddenly notices that there appears to be some kind of order in their sequence. Many pairs of successive cards are either of the same rank or of the same suit. “This might be a nice little puzzle,” says Walter to himself. “I wonder if I can rearrange the sequence so that each two consecutive cards share either the rank or the suit. But wait, the pack looks to be incomplete, that might severely limit the arrangement possibilities, hmm...”

Help Walter determine whether his puzzle is solvable.

Input Specification

There are more test cases. Each test case consists of a single line on which all cards in the pack are listed. The list starts with one integer L (1 ≤ L ≤ 52), denoting the number of cards in the pack, followed by a space and L card descriptions. Each card is described by a two character string. The first character denotes the rank of the card (“A”=Ace, “2”–“9”, “X”=10, “J”=Jack,“Q”=Queen, “K”=King) and the second character denotes the suit of the card (“C”=Clubs,“D”=Diamonds, “H”=Hearts, “S”=Spades). The successive card descriptions are separated by one space.

Output Specification

For each test case, print a single line with the string “YES” if the puzzle is solvable or a line with the string “NO” if the puzzle is not solvable.

样例输入

8 2C 2D 2H 2S XC JS QS KS
4 5C 4H AS 9D

样例输出

YES
NO

    先来解释一下题意,题目是说有52张扑克牌(就是普通的扑克牌去掉大小王),然后现在想要将这些扑克牌排成一列,要求相邻的两个扑克牌要不然保持数字一样要不然保持花色一样,但是这套牌并不完整,问是否能按照要求将给出的牌排成一列。

    做计蒜客ACM ICPC 2017 Warmup Contest 7中的一道题目,本想着做这个比赛练练手,结果做完发现这题网上根本搜不到题解= =之前的思路是建的图然后跑dfs,不过那样会超时,之后减了一下午的枝也没能把这题给A出来。因为没有题解所以搜了好久弄到了别人的AC代码,然后才补了这道题。(所以今天的ACM ICPC 2017 Warmup Contest 8我们没再做,怕又遇见个题不会做还没个题解就难受了= =区域赛没几天了)

   这道题目我一开始是用的构建图,但是这样太慢,其实不需要构建出来一个完整的图将能连接的卡片都连上,因为花色只有4种,所以将有没有这4种花色进行分类讨论来处理就可以了,在读入数据的时候,将数字相同的卡片连接起来,而花色相同的卡牌暂时不用管,只需要记录出现过没有,出现了几张以备讨论。

    对于只有一种花色的情况,很明显是可以排成一排的。

    对于只有两种花色的情况,只要能找出两张数字一样的牌就说明可以全部排成一排。因为之前我们只连接了数字相同的牌,所以这里跑一个循环看一看有没有两张牌连接了起来就足够了。

    对于有三种花色的情况,假设这三种花色为a,b,c,那么找出是否存在a和b花色有相同的一个数字牌i,b和c花色有一个相同的数字牌j(i≠j),这样的话这一列就可以相互接起来,然后构成一排,不过还存在一种特殊情况,如果b花色的牌只有一张的话,那么i=j也是可以排成一排的,因为这样这一张牌不再需要连接更多的牌,直接一串连下来就可以了。

    至于四种花色的情况,其实就是相比于三种花色的情况多考虑一层,三种花色是要找两个连接点,这个则是找四个连接点。除此之外除了a-b-c-d这样的花色连法,因为有四个数,所以还可以出现a-b-c-b-d的这种连法,然后再分开考虑一下b的情况。

    (PS:之前的代码本地能过但是到了OJ里答案就完全不一样,最后发现是mar数组我觉得只有4个数所以开了15的数组,但是他要识别的是ASCII码,所以15的数组肯定是不够用的,但是本地为什么能对啊= =)

    下面AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,mp[55][55],mar[105],num[15];char s[55][3];int charint(char ch){    if(ch=='A')        return 0;    if(ch=='X')        return 9;    if(ch=='J')        return 10;    if(ch=='Q')        return 11;    if(ch=='K')        return 12;    return ch-'0'-1;}int connect1(int a,int b){    int x,y;    x=mar[(int)s[a][1]]*13+charint(s[a][0]);    y=mar[(int)s[b][1]]*13+charint(s[b][0]);    mp[x][y]=mp[y][x]=1;    //cout<<x<<" "<<y<<endl;    return 0;}int check3(int a,int b,int c){    int i,j;    for(i=0;i<13;i++)    {        if(mp[a*13+i][b*13+i])            for(j=0;j<13;j++)            {                if((i!=j||num[b]==1)&&mp[b*13+j][c*13+j])                    return 1;            }    }    return 0;}bool check4(int a,int b,int c,int d){    int i,j,k,g;    for(i=0;i<13;i++)    {        if(mp[a*13+i][b*13+i])            for(j=0;j<13;j++)            {                if((i!=j||num[b]==1)&&mp[b*13+j][c*13+j])                    for(k=0;k<13;k++)                    {                        if((j!=k||num[c]==1)&&mp[c*13+k][d*13+k])                            return 1;                    }            }    }    for(i=0;i<13;++i)    {        if(mp[a*13+i][b*13+i])            for(j=0;j<13;++j)            {                if(mp[b*13+j][c*13+j])                    for(k=0;k<13;k++)                    {                        if(j!=k&&mp[c*13+k][b*13+k])                            for(g=0;g<13;g++)                            {                                if(i!=g&&j!=g&&(k!=g||num[b]==2)&&mp[b*13+g][d*13+g])                                    return 1;                            }                    }            }    }    for(i=0;i<13;i++)    {        if(mp[a*13+i][b*13+i])            for(j=0;j<13;j++)            {                if(i!=j&&mp[b*13+j][c*13+j])                    for(k=0;k<13;k++)                    {                        if(j!=k&&mp[c*13+k][b*13+k])                            for(g=0;g<13;g++)                            {                                if(i!=g&&j!=g&&mp[b*13+g][d*13+g])                                    return 1;                            }                    }            }    }    return 0;}int main(){    int i,j,k,g;    int tot;    bool flag;    mar[(int)'C']=0;    mar[(int)'D']=1;    mar[(int)'H']=2;    mar[(int)'S']=3;    while(scanf("%d",&n)!=EOF)    {        getchar();        tot=0;        flag=0;        memset(num,0,sizeof(num));        memset(mp,0,sizeof(mp));        for(i=0;i<n;++i)        {            scanf("%s",s[i]);            num[mar[(int)s[i][1]]]++;            for(j=0;j<i;j++)            {                if(s[j][0]==s[i][0]&&s[j][1]!=s[i][1])                    connect1(i,j);            }        }        for(i=0;i<4;i++)        {            if(num[i])                tot++;        }        if(tot==1)            flag=1;        else if(tot==2)        {            for(i=0;i<52;i++)            {                for(j=i+1;j<52;j++)                {                    if(mp[i][j])                        flag=1;                    if(flag)                        break;                }                if(flag)                    break;            }        }        else if(tot==3)        {            for(i=0;i<4;i++)            {                for(j=0;j<4;j++)                {                    if(i!=j)                        for(k=0;k<4;k++)                        {                            if(i!=k&&j!=k)                                if(check3(i,j,k))                                    flag=1;                            if(flag)                                break;                        }                    if(flag)                        break;                }                if(flag)                    break;            }        }        else        {            for(i=0;i<4;i++)            {                for(j=0;j<4;j++)                {                    if(i!=j)                        for(k=0;k<4;k++)                        {                            if(i!=k&&j!=k)                                for(g=0;g<4;g++)                                {                                    if(i!=g&&j!=g&&k!=g)                                        if(check4(i,j,k,g))                                            flag=1;                                    if(flag)                                        break;                                }                            if(flag)                                break;                        }                    if(flag)                        break;                }                if(flag)                    break;            }        }        if(flag)            cout<<"YES"<<endl;        else            cout<<"NO"<<endl;    }    return 0;}



原创粉丝点击