题意
Alice 和 Mukyu 最近偶然得到了一本写有一种叫做梭哈的扑克游戏的规则的说明书(名为《C████████nd》,中间部分被涂掉了),据其所述,梭哈是一种使用黑桃、红心、梅花、方片的 A 到 K 共 52 张牌(没有大小王)来进行的扑克牌游戏。
不幸的是,规则说明中有关整个游戏的进行方式的部分被撕掉了,Alice 和 Mukyu 从残存的部分只得知了“手牌上限是 5 张”这一消息,所以他们决定每次直接给两人各发 5 张牌,判定谁的手牌比较大,说明书中关于手牌大小判定的信息如下:
所有五张牌的组合,按以下秩序,由大至小排行分为不同牌型:
1、同花顺(Straight Flush):同一花色,顺序的牌。 例: Q♦ J♦ 10♦ 9♦ 8♦;
2、四条(Four of a Kind):有四张同一点数的牌。 例: 10♣ 10♦ 10♥ 10♠ 9♥;
3、满堂红(Full House):三张同一点数的牌,加一对其他点数的牌。 例: 8♣ 8♦ 8♠ K♥ K♠;
4、同花(Flush):五张同一花色的牌。 例: A♠ K♠ 10♠ 9♠ 8♠;
5、顺子(Straight):五张顺连的牌。 例: K♦ Q♥ J♠ 10♦ 9♦;
6、三条(Three of a kind):有三张同一点数的牌。 例: J♣ J♥ J♠ K♦ 9♠;
7、两对(Two Pairs):两张相同点数的牌,加另外两张相同点数的牌。 例: A♣ A♦ 8♥ 8♠ Q♠;
8、一对(One Pair):两张相同点数的牌。 例: 9♥ 9♠ A♣ J♠ 8♥;
9、无对(Zilch):不能排成以上组合的牌,以点数决定大小。例: A♦ Q♦ J♠ 9♣ 8♣。
若牌型一样则利用点数和花色决定胜负。(点数优先)
点数的顺序(从大至小)为:A>K>Q>J>10>9>8>7>6>5>4>3>2。(注:当 5 张手牌是 5 4 3 2 A 的时候,A 可以看作最小的牌,此时的牌型仍然为顺子,是顺子里面最小的一个)。
花色的顺序(大至小)为:黑桃(♠)>红心(♥)>梅花(♣)>方块(♦)。
举例说明:
1、Q♦ J♦ 10♦ 9♦ 8♦ > 8♣ 8♥ 8♠ K♥ K♠ (前者牌型为同花顺,比后者大);
2、9♣ 9♦ 9♠ Q♥ Q♠ > 8♣ 8♦ 8♠ K♥ K♠ (两者牌型均为满堂红,比较牌型中三张同一点数的牌 9 比 8 大);
3、A♣ A♦ 8♥ 8♠ Q♠ > A♠ A♥ 7♥ 7♠ K♠ (两者牌型均为两对,且最大的对子相同,此时比较次大的对子,8 比 7 大);
4、A♠ Q♠ J♥ 9♥ 8♥ > A♦ Q♦ J♠ 9♣ 8♣ (两者牌型均为无对,所有数码均相同,此时比较最大牌的花色,A♠ > A♦)。
5、4♠ 4♥ A♦ Q♦ 5♦ > 4♣ 4♦ A♠ Q♠ 5♠ (两者牌型均为一对,所有数码均相同,此时对 4 为牌型里最大的部分,因此比较 4♠ > 4♣)
”
尽管 Alice 和 Mukyu 都可以轻易的判断出结果,他们还是想见识一下现代科技的力量。
输入格式
第一行包含一个正整数 N,表示有 N 组测试数据。
每组测试数据包含 10 行,前 5 行每行用两个整数描述一张 Alice 手上的牌,第一个数表示牌的数码(1 表示 A,13 表示 K),第二个数表示牌的花色(1 表示黑桃,2 表示红心, 3 表示梅花,4 表示方块)。
后 5 行每行用两个整数描述 Mukyu 手上的牌,格式同上。
输出格式
对于每组测试数据,在单独的一行内输出 Alice 或 Mukyu,表示谁能赢。
样例输入
1
1 3
5 3
4 3
3 3
2 3
6 1
10 4
7 1
8 1
9 2
样例输出
Alice
样例解释
Alice 的手牌构成同花顺,而 Mukyu 的手牌仅构成普通顺子。
数据范围
对于 10%的数据,保证输入的全部牌型都是无对。
对于另外 30%的数据,保证输入的全部牌型都是顺子、同花或同花顺。
对于 100%的数据,保证 N ≤ 100000。
C++选手如果使用 cin 读入数据很可能因此超时,推荐使用 scanf/printf。
解析
一道大模拟,按照题意模拟即可,细节还是蛮多的,我们可以按照5张牌中花色的种类和点数的种类以及出现最多的相同点数的次数分类,于是便只需细分顺子,同花顺,同花,按照题意特殊处理 $ A $即可。特别注意的是在一些情况中 $ A $ 是看作14的,有时看作1,这个代码里有详细注释。
代码
#include<bits/stdc++.h>
using namespace std;
struct node{
int data;//点数
int col;//花色
}b[10],c[20];
struct Node{
int data;//点数
int col;//花色
int num;//种类
};
int n,ans;
bool cmp(node a,node b){
return a.data<b.data;
}
node find(node a[]){
int maxcol=0;//最大花色
int maxdata=0;//最大点数
node p;
for(int i=5;i>=1;--i){//逆过来!
if(a[i].data>=maxdata){
maxdata=a[i].data;
maxcol=max(a[i].col,maxcol);
}
}
p.data=maxdata;
p.col=maxcol;
return p;
}
Node cheak(node a[]){
int mdata=0;//点数种类
int mcol=0;//花色种类
int mcom=0;//某个点数出现最多的次数
int book[20];
memset(book,0,sizeof(book));
for(int i=1;i<=5;++i){//找花色种类
if(!book[a[i].col]){
book[a[i].col]=1;
mcol++;
}
}
memset(book,0,sizeof(book));
for(int i=1;i<=5;++i){//找点数种类 及 次数
if(!book[a[i].data]){
book[a[i].data]++;
mdata++;
}else{
book[a[i].data]++;
mcom=max(mcom,book[a[i].data]);
}
}
if(mcol==4&&mdata==2&&mcom==4){//四条,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=2;
return ans;
}
else if(mcol>=3&&mdata==2&&mcom==3){//满堂红,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=3;
return ans;
}
else if(mcol>=3&&mdata==3&&mcom==3){//三条,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=6;
return ans;
}
else if(mcol>=2&&mdata==3&&mcom==2){//两对,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=7;
return ans;
}
else if(mcol>=2&&mdata==4&&mcom==2){//一对,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=8;
return ans;
}
else if(mcol>=1&&mdata==5&&mcom==0){//同花顺,同花,顺子
if(mcol>1){//顺子
bool flag=1;
for(int i=2;i<5;++i){//判断2-5是不是连着的
if(a[i+1].data!=a[i].data+1) flag=0;
}
if(flag){
bool tmp=1;
for(int i=2;i<=5;++i){//判断是不是10-A
if(a[i].data!=i+8)tmp=0;
}
if((a[2].data==a[1].data+1)||(tmp&&a[1].data==1)) flag=1;//是不是顺子
else flag=0;
}
if(!flag){//无对特判
for(int i=5;i>=1;--i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=9;
return ans;
}
node tmp=find(a);
Node ans;
ans.col=tmp.col;
if(a[1].data==1&&a[2].data!=2){//判断是不是10-A
ans.data=14;
ans.col=a[1].col;
}
else ans.data=tmp.data;
ans.num=5;
return ans;
}else{
bool flag=1;
for(int i=1;i<5;++i){//判断2-5是不是连着的
if(a[i+1].data!=a[i].data+1) flag=0;
}
if(flag){
bool tmp=1;
for(int i=2;i<=5;++i){//判断是不是10-A
if(a[i].data!=i+8) tmp=0;
}
if((a[2].data==a[1].data+1)||(tmp&&a[1].data==1)) flag=1; //是不是顺子
else flag=0;
}
if(flag){//同花顺
node tmp=find(a);
Node ans;
ans.col=tmp.col;
if(a[1].data==1&&a[2].data==2) ans.data=1;
else if(a[1].data==1) ans.data=14;
else ans.data=tmp.data;
ans.num=1;
return ans;
}
else{//同花
for(int i=1;i<=5;++i){//把1换成A无影响
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=4;
return ans;
}
}
}
else{//无对
for(int i=5;i>=1;--i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=9;
return ans;
}
}
bool judge(Node x1,Node y1){//判断谁赢
if(x1.num<y1.num) return true;
else if(x1.num>y1.num) return false;
else{
if(x1.num==2||x1.num==3||x1.num==6){//四条,满堂红,三条特判
return b[3].data>c[3].data;//一定在中间 且不需要比较花色
}
if(x1.num==4){//同花特判
for(int i=5;i>=1;--i){//单牌比较
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(x1.col>y1.col) return true;
else return false;
}
if(x1.num==7){//两对特判
int tmp1=0;
int tmp2=0;
int tmp3=0;
int tmp4=0;
for(int i=1;i<5;++i){//第一副牌的两个对子
if(b[i].data==b[i+1].data){
if(!tmp1)tmp1=i;
else tmp3=i;
}
if(c[i].data==c[i+1].data){//第二幅牌
if(!tmp2)tmp2=i;
else tmp4=i;
}
}
if(b[tmp1].data<b[tmp3].data) swap(tmp1,tmp3);//保证1,2更大
if(b[tmp2].data<b[tmp4].data) swap(tmp2,tmp4);
if(b[tmp1].data>c[tmp2].data) return true;//第一大的对子比较
else if(b[tmp1].data<c[tmp2].data) return false;
else{
if(b[tmp3].data>c[tmp4].data) return true;//第二大的对子比较
else if(b[tmp3].data<c[tmp4].data) return false;
else{
for(int i=5;i>=1;--i){//单牌比较
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(max(b[tmp1].col,b[tmp1+1].col)>max(b[tmp2].col,b[tmp2+1].col)) return true;//数码相同,颜色比较
else return false;
}
}
}
else if(x1.num==8){//单对特判
int tmp1=0;
int tmp2=0;
for(int i=1;i<5;++i){//找对子
if(b[i].data==b[i+1].data) tmp1=i;
if(c[i].data==c[i+1].data) tmp2=i;
}
if(b[tmp1].data>c[tmp2].data) return true;
else if(b[tmp1].data<c[tmp2].data) return false;
else{
for(int i=5;i>=1;--i){
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(b[tmp1].col>c[tmp2].col) return true;
else return false;
}
}
else if(x1.num==9){//散牌
for(int i=5;i>=1;--i){
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(b[5].col>c[5].col) return true;//因为把A换成13所以比较最后一个
else return false;
}
else{//顺子可直接判断
if(x1.data>y1.data) return true;
else if(x1.data<y1.data) return false;
else{
if(x1.col>y1.col) return true;
else return false;
}
}
}
}
int main(){
//freopen("ptgiving.in","r",stdin);
//freopen("ptgiving.out","w",stdout);
scanf("%d",&n);
while(n--){
for(int i=1;i<=5;++i){
scanf("%d %d",&b[i].data,&b[i].col);
b[i].col=5-b[i].col;//转化花色
}
sort(b+1,b+6,cmp);
Node tmp1=cheak(b);
for(int i=1;i<=5;++i){
scanf("%d %d",&c[i].data,&c[i].col);
c[i].col=5-c[i].col;//转化花色
}
sort(c+1,c+6,cmp);
Node tmp2=cheak(c);
if(judge(tmp1,tmp2)) printf("Alice\n");
else printf("Mukyu\n");
}
return 0;
}