BUPT Summer Journey #test5 E

 

E. 机智的学姐 2014新生暑假个人排位赛05

时间限制 1000 ms     内存限制 65536 KB    

题目描述

斗地主玩法简单,娱乐性强,老少皆宜。据传在万恶的旧社会,地主横行乡里,无恶不做,人们为了发泄对地主的痛恨,常常在一天的劳作之后,一家人关起门来“斗地主”。该游戏由三人玩一副牌,地主为一方,其余两家为另一方,双方对战,先出完手中牌的一方胜。
机智的学姐已经通过某些不和谐的手段,得到了下家手上的牌型,可是学姐的机智值全都用来得到下家牌型了。她非常想知道自己是不是有一种出牌的方法,使得下家没有办法能大过自己,这个艰难的任务就交给你了。(不用判断输赢,只需判断这一轮牌有没有好的策略使下家没法大过自己)
关于牌型比较
火箭:即双王(大王和小王),最大的牌。
炸弹:四张同数值牌(如四个7)。
单牌:单个牌(如一张5)。
对牌:数值相同的两张牌(如一对4)。
三张牌:数值相同的三张牌(如三个J)。
三带一:数值相同的三张牌 + 一张单牌或一对牌。例如:333+6 或 444+99。
单顺:五张或更多的连续单牌(如:45678 或 78910JQK)。不包括 2 点和双王。
双顺:三对或更多的连续对牌(如:334455 、77 88 99 1010 JJ)。不包括 2 点和双王。
三顺:二个或更多的连续三张牌(如:333444 、 555 666 777 888)。不包括 2 点和双王。
飞机带翅膀:三顺+同数量的单牌(或同数量的对牌)。
如: 444555+79 或 333444555+7799JJ。
四带二:四张牌+两手牌(注意:四带二不是炸弹)。
如: 5555+3+8 或 4444+55+77。

关于牌型大小
火箭最大,可以打任意其他的牌。
炸弹比火箭小,比其他牌大。都是炸弹时按牌的分值比大小。
除火箭和炸弹外,其他牌必须要牌型相同且总张数相同才能比大小。相同牌型按牌的分值比大小。
依次是 大王 > 小王 >2>A>K>Q>J>10>9>8>7>6>5>4>3 ,不分花色。

输入格式

为了处理方便,我们用Y表示大王,X表示小王,T表示10。
所有牌都用A23456789TJQKXY表示,两家牌的数量小于20。
每组数据两行,有多组数据,EOF结束。

输出格式

每个测试数据一行Yes或者No

输入样例

A334455
23456789
23456
456789
AJJJ
3333

输出样例

Yes
Yes
No

思路:这题给你上家的牌,让你判断下家的牌有没有大过他的。首先可以预处理出上下家手里的牌,然后对每一种出牌方式枚举,若存在一种出牌方式下家没有大过他的就为Yes,

若扫描完所有情况都有打过它的就为No.

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define LOCAL
using namespace std;
char str1[50],str2[50];
struct type
{
    int sg[16];//单牌
    int cp[14];//对牌
    int tp[14][3];//三张牌
    int sgs[13][9];//单顺
    int cps[11][11];//双顺
    int tps[7][12][3];//三顺
    int bomb[14][3];//炸弹
}A,B;
void Init(type &x,char str[])
{
    int i,j,k,len=strlen(str);
    memset(&x,0,sizeof(x));
    for(int i=0;i<len;i++)//处理单牌
    {
        int t;
        if(str[i]>='3'&&str[i]<='9')t=str[i]-'2';
        else if(str[i]=='T')t=8;
        else if(str[i]=='J')t=9;
        else if(str[i]=='Q')t=10;
        else if(str[i]=='K')t=11;
        else if(str[i]=='A')t=12;
        else if(str[i]=='2')t=13;
        else if(str[i]=='X')t=14;
        else if(str[i]=='Y')t=15;
        x.sg[t]++;
        if(x.sg[0]<t)x.sg[0]=t;/**/
    }
    for(int i=1;i<=13;i++)//处理对牌,三张牌,炸弹
    {
        if(x.sg[i]>1)
        {
            x.cp[i]=1;
            x.cp[0]=i;
        }
        if(x.sg[i]>2)
        {
            x.tp[i][0]=1;
            x.tp[0][0]=i;
        }
        if(x.sg[i]>3)
        {
            x.bomb[i][0]=1;
            x.bomb[0][0]=i;
        }
    }
    for(i=1;i<=13;i++)//处理三带一,三带二
    {
        if(x.tp[i][0]==0)continue;
        for(j=1;j<=15;j++)
        {
            if(j==i)continue;
            if(x.sg[j])
            {
                x.tp[i][1]=1;
                x.tp[0][1]=i;
                break;
            }
        }
        for(j=1;j<=13;j++)
        {
            if(j==i)continue;
            if(x.cp[j])
            {
                x.tp[i][2]=1;
                x.tp[0][2]=i;
                break;
            }
        }
    }
    for(i=1;i<=8;i++)//小五张
        if(x.sg[i]&&x.sg[i+1]&&x.sg[i+2]&&x.sg[i+3]&&x.sg[i+4])
        {
            x.sgs[5][i]=1;
            x.sgs[5][0]=i;
        }
    for(i=6;i<=12;i++)//大于五张
        for(j=1;i+j-1<=12;j++)
            if(x.sgs[i-1][j]&&x.sg[i+j-1])
            {
                x.sgs[i][j]=1;
                x.sgs[i][0]=j;
            }
    for(i=1;i<=10;i++)//三对
        if(x.cp[i]&&x.cp[i+1]&&x.cp[i+2])
        {
            x.cps[3][i]=1;
            x.cps[3][0]=i;
        }
    for(i=4;i<=12;i++)//大于三对
        for(j=1;i+j-1<=12;j++)
            if(x.cps[i-1][j]&&x.cp[i+j-1])
            {
                x.cps[i][j]=1;
                x.cps[i][0]=j;
            }
    for(i=1;i<=11;i++)//两个三组
        if(x.tp[i][0]&&x.tp[i+1][0])
        {
            x.tps[2][i][0]=1;
            x.tps[2][0][0]=i;
        }
    for(i=3;i<=6;i++)//大于两个三组
        for(j=1;i+j-1<=12;j++)
            if(x.tps[i-1][j][0]&&x.tp[i+j-1][0])
            {
                x.tps[i][j][0]=1;
                x.tps[i][0][0]=j;
            }
    for(i=2;i<=6;i++)//飞机
    {
        for(j=1;i+j-1<=12;j++)
        {
            if(x.tps[i][j][0]==0)continue;
            int cnt=0;
            for(k=1;k<=15;j++)
            {
                if(k>=j&&k<=i+j-1)continue;
                if(x.sg[j])cnt+=x.sg[j];
                if(cnt>=i)
                {
                    x.tps[i][j][1]=1;
                    x.tps[i][0][1]=j;
                    break;
                }
            }
            cnt=0;
            for(k=1;k<=13;k++)
            {
                if(k>=j&&k<=i+j-1)continue;
                if(x.cp[j])cnt++;
                if(cnt==i)
                {
                    x.tps[i][j][2]=1;
                    x.tps[i][0][2]=j;
                    break;
                }
            }
        }
    }
}
int main()
{
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif // LOCAL
    while(scanf("%s%s",str1,str2)==2)
    {
        Init(A,str1);
        Init(B,str2);
        if(A.sg[14]&&A.sg[15])//若同时有大王小王,则必没有可以大过他的。反之亦然。
        {
            printf("Yes\n");
            continue;
        }
        else if(B.sg[14]&&B.sg[15])
        {
            printf("No\n");
            continue;
        }
        if(A.bomb[0][0]>=B.bomb[0][0]&&A.bomb[0][0]>0)//若A持有的最大的炸弹比B大且不等于0,则必无法大过A,反之亦然
        {
            printf("Yes\n");
            continue;
        }
        if(A.bomb[0][0]<B.bomb[0][0])
        {
            printf("No\n");
            continue;
        }
        if((A.sg[0]>=B.sg[0]&&A.sg[0])||(A.cp[0]>=B.cp[0]&&A.cp[0])||(A.tp[0][0]>=B.tp[0][0]&&A.tp[0][0])||(A.tp[0][1]>=B.tp[0][1]&&A.tp[0][1])||(A.tp[0][2]>=B.tp[0][2]&&A.tp[0][2]))//若A持有的最大的单牌,对牌,三张牌,三带一,三带二比大于等于B且不为0则必没有大过的
        {
            printf("Yes\n");
            continue;
        }
        int flag=0;
        for(int i=5;i<=12;i++)
            if(A.sgs[i][0]>=B.sgs[i][0]&&A.sgs[i][0])//若A存在i个单顺的最大大于B的i个单顺最大则标记能大于等于B且不为0,跳出
            {
                flag=1;
                break;
            }
        for(int i=3;i<=10;i++)
            if(A.cps[i][0]>=B.cps[i][0]&&A.cps[i][0])//若A存在i个双顺的最大大于B的i个双顺最大则标记能大于等于B且不为0,跳出
            {
                flag=1;
                break;
            }
        for(int i=2;i<=6;i++)
            if((A.tps[i][0][0]>=B.tps[i][0][0]&&A.tps[i][0][0])||(A.tps[i][0][1]>=B.tps[i][0][1]&&A.tps[i][0][1])||(A.tps[i][0][2]>=B.tps[i][0][2]&&A.tps[i][0][2]))//若A存在i个三顺的最大大于B的i个三顺最大则标记能大于等于B且不为0或A存在i个飞机带翅膀的最大大于B的i个飞机带翅膀最大则标记能大于等于B且不为0,跳出
            {
                flag=1;
                break;
            }
        if(flag==1)
        {
            printf("Yes\n");
            continue;
        }
        else
        {
            printf("No\n");
            continue;
        }
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值