题意:就是普通的斗地主,问你第一个人能不能打败第二个人
注意点:
1.三张牌出牌带的必须的一对,而四张牌带的可以是两张不同的
2.第一个人打完牌他就赢了,不用考虑后面的人
思路:
一共有8种出牌方法,前面6种只能按照牌面大小打败相同的出牌类型
但是最后两种,也是就玩炸和炸弹可以打败其他的出牌类型;
因此,我们考虑计算出每一个出牌类型,能出的最大的权重,
如果是最后两种就把他们的权重更新到其他6种出牌类型里面
最后统计的时候要注意的是:
1.第一个人的某一种出牌类型为0的时候不能比较,因为如果第二个人这一种出牌类型的最大权重也为0也就是说,他不能出这种牌,用大于等于判断的时候就会出错
2.第二个人出光手牌的情况不能被考虑,因为第二个人只能出与第一个人对应的出牌类型.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
const int Bomb=1e6; //炸弹的权重
const int Nuke=1e7;//玩炸的权重
const int EMPTY_HAND=1e9;//一次能光打牌的权重
bool is_first;//是否是第一个人
int card[16],apro[7],bpro[7];//各种权重卡片的个数,a的各种出牌类型的最大权重,b的各种出牌类型的最大权重
int *pro;//当前计算时权重的存储位置
int prio_ch(char a) //卡牌权重转换函数,从小到大
{
switch(a)
{
case 'Y':
return 15;
case 'X':
return 14;
case '2':
return 13;
case 'A':
return 12;
case 'K':
return 11;
case 'Q':
return 10;
case 'J':
return 9;
case 'T':
return 8;
case '9':
case '8':
case '7':
case '6':
case '5':
case '4':
case '3':
return a-'0'-2;
}
}
void setv(int i,int v) //用v更新i类型出牌的最大权重
{
pro[i]=max(pro[i],v);
}
void setall(int v) //用v更新全部类型出牌的最大权重
{
if(!is_first && v==EMPTY_HAND) return ; //如果不是第一个人打光手牌的话则返回
for(int i=1;i<=6;i++) pro[i]=max(pro[i],v);
}
void cal(string a)
{
memset(card,0,sizeof(card));//初始化
int n=a.size(),npair=0;
for(int i=0;i<n;i++)
card[prio_ch(a[i])]++; //计数
if(card[15] && card[14]) //大小王都有就更新全部出牌类型为玩炸
setall(Nuke);
if(n==1) //只有一张牌,所以可以打光
setall(EMPTY_HAND);
for(int i=1;i<=15;i++) //计算只出一张牌,也就是第一种出牌类型的权重
{
if(card[i]) setv(1,i);
}
for(int i=1;i<=15;i++) //第二种出牌类型的权重
{
if(card[i]>=2)
{
npair++; //计算不同对子的个数
setv(2,i);
}
}
if(npair!=0 && n==2) //打一对就可以打完
setall(EMPTY_HAND);
int ntri=0; //三张一样的对数
for(int i=1;i<=15;i++) //计算第三,四,五种出牌类型的权重
{
if(card[i]>=3) //有三张以上
{
ntri++;
setv(3,i);
if(n-card[i]>=1) //出了三张,至少还有一张是不同的
setv(4,i);
if(npair>=2) //出了这三张,还可以出一对,因为3这本身三张也算是一对,所以要大于等于2
setv(5,i);
}
}
if((n==3 && ntri==1) || (n==5 && ntri==3 && npair==2)) //一次出三张就打完了,或者 一次出5张 ,就是三张带一对
setall(EMPTY_HAND);
if(ntri==1 && n==4) setall(EMPTY_HAND); //三张带一条
int ntrio=0; //四张一起的
for(int i=1;i<=15;i++)
{
if(card[i]==4)
{
ntrio++;
setall(Bomb+i); //更新全部出牌类型炸弹,因为炸弹是可以当成任意出牌类型的
if(n>=6)
setv(6,i); //出四张 ,加两张,注意这两张可以是不同的
}
}
if((n==4 && ntrio==1) || (ntrio==1 && n==6)) //出四张带一张,还有,带两张
setall(EMPTY_HAND);
}
int main()
{
// freopen("in","r",stdin);
// freopen("out","w",stdout);
int T;
scanf("%d", &T);
while(T--)
{
string a,b;
cin>>a>>b;
memset(apro,0,sizeof(apro));
memset(bpro,0,sizeof(bpro));
is_first=true; //第一个先手
pro=apro;
cal(a);
is_first=false;//不是先手
pro=bpro;
cal(b);
bool win=false;
for(int i=1; i<=6; i++)
{
if(apro[i] && apro[i]>=bpro[i]) //某一种出牌的权重大于第二个人就可以赢了
{
win=true;
break;
}
}
puts(win?"Yes":"No");
}
return 0;
}