问题描述:
最近,东东沉迷于打牌。所以他找到 HRZ、ZJM 等人和他一起打牌。由于人数众多,东东稍微修改了亿下游戏规则:
所有扑克牌只按数字来算大小,忽略花色。
每张扑克牌的大小由一个值表示。A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K 分别指代 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13。
每个玩家抽得 5 张扑克牌,组成一手牌!(每种扑克牌的张数是无限的,你不用担心,东东家里有无数副扑克牌)
理所当然地,一手牌是有不同类型,并且有大小之分的。
举个栗子,现在东东的 “一手牌”(记为 α),瑞神的 “一手牌”(记为 β),要么 α > β,要么 α < β,要么 α = β。
那么这两个 “一手牌”,如何进行比较大小呢?首先对于不同类型的一手牌,其值的大小即下面的标号;对于同类型的一手牌,根据组成这手牌的 5 张牌不同,其值不同。下面依次列举了这手牌的形成规则:
大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。
对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 “对子” 的大小,如果 α 和 β 的 “对子” 大小相等,那么比较剩下 3 张牌的总和。
两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。
三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 “三个”,比较这个 “三个” 的大小,如果 α 和 β 的 “三个” 大小相等,那么比较剩下 2 张牌的总和。
三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 “三带二”,先比较它们的 “三个” 的大小,如果相等,再比较 “对子” 的大小。
炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 “炸弹”,比较 “炸弹” 的大小,如果相等,比较剩下那张牌的大小。
顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 “顺子”,直接比较两个顺子的最大值。
龙顺:5 张牌分别为 10、J、Q、K、A。
作为一个称职的魔法师,东东得知了全场人手里 5 张牌的情况。他现在要输出一个排行榜。排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。
不料,此时一束宇宙射线扫过,为了躲避宇宙射线,东东慌乱中清空了他脑中的 Cache。请你告诉东东,全场人的排名
Input:
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。
Output:
对于每组测试数据,输出 n 行,即这次全场人的排名。
Sample Input:
3
DongDong AAA109
ZJM 678910
Hrz 678910
Sample Output:
Hrz
ZJM
DongDong
解题思路:
这道题前面已经做过类似的且难度更高的,我的思路就是创建一个结构体,数据成员有牌手名,字符串描述的牌pai,Ptype描述了牌型,card描述了14张牌的拥有情况。定义了一个全局函数:clac_type函数,这个函数实现也不难,就是对字符串pai判断牌号,遍历这个字符串,记录到card数组里,表示每张牌的拥有情况,接下来就是判断牌型,这里还定义了一个变量differ,这个变量表明了五张牌中有几张不同的,若是有五个,说明这个牌牌型只能是大牌、顺子和龙顺,龙顺直接判断五张牌是否符号条件即可,顺子的话只要有一张牌为1了(即card[i],后面的四张牌也必须全是1,否则不是退出判断,该牌为大牌。如果differ不为1,就有一个循环,遍历card数组,记录牌数为1的有几个,牌数为i的有几个,方便后面直接进行牌型判断。如:炸弹就是cnt[4]=1=或者cnt[5]==1,其他类似判断即可。
最后就是结构体中比较函数的设计部分,这个部分逻辑比较简单,最后对player数组排序输出牌手名即可。
实验代码:
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
string paihao=".A23456789.JQK";
int cfind(char s) //查找牌号
{
for(int i=1;i<14;i++)
if(s==paihao[i])
return i;
}
int n;
struct player
{
//数据成员
string name;
string pai;
int Ptype;
int card[14];
//比较函数
bool operator<(const player& p) const
{
if(Ptype!=p.Ptype)
return Ptype>p.Ptype;
if(Ptype==1)
{
int sum1=0,sum2=0;
for(int i=1;i<14;i++)
if(card[i]==1)
sum1+=i;
for(int i=1;i<14;i++)
if(p.card[i]==1)
sum2+=i;
if(sum1!=sum2)
return sum1>sum2;
return name<p.name;
}
if(Ptype==2)
{
int sum1=0,Psum1=0,num2,Pnum2;
for(int i=1;i<14;i++)
{
if(card[i]==0) continue;
if(card[i]==1) sum1+=i;
else num2=i;
}
for(int i=1;i<14;i++)
{
if(p.card[i]==0) continue;
if(p.card[i]==1) Psum1+=i;
else Pnum2=i;
}
if(num2!=Pnum2) return num2>Pnum2;
if(sum1!=Psum1) return sum1>Psum1;
return name<p.name;
}
if(Ptype==3) //两对
{
int num1,Pnum1,num2[2],num2_index=0,Pnum2[2],Pnum2_index=0;
for(int i=1;i<14;i++)
{
if(card[i]==0) continue;
if(card[i]==2) num2[num2_index++]=i;
else num1=i;
}
for(int i=1;i<14;i++)
{
if(p.card[i]==0) continue;
if(p.card[i]==2) Pnum2[Pnum2_index++]=i;
else Pnum1=i;
}
if(num2[1]!=Pnum2[1]) return num2[1]>Pnum2[1];
if(num2[0]!=Pnum2[0]) return num2[0]>Pnum2[0];
if(num1!=Pnum1) return num1>Pnum1;
return name<p.name;
}
if(Ptype==4) //三个
{
int num3,Pnum3,sum1=0,Psum1=0;
for(int i=1;i<14;i++)
{
if(card[i]==0) continue;
if(card[i]==1) sum1+=i;
else num3=i;
}
for(int i=1;i<14;i++)
{
if(p.card[i]==0) continue;
if(p.card[i]==1) Psum1+=i;
else Pnum3=i;
}
if(num3!=Pnum3) return num3>Pnum3;
if(sum1!=Psum1) return sum1>Psum1;
return name<p.name;
}
if(Ptype==5) //三带二
{
int num2,Pnum2,num3,Pnum3;
for(int i=1;i<14;i++)
{
if(card[i]==0) continue;
if(card[i]==2) num2=i;
if(card[i]==3) num3=i;
}
for(int i=1;i<14;i++)
{
if(p.card[i]==0) continue;
if(p.card[i]==2) Pnum2=i;
if(p.card[i]==3) Pnum3=i;
}
if(num3!=Pnum3) return num3>Pnum3;
if(num2!=Pnum2) return num2>Pnum2;
return name<p.name;
}
if(Ptype==6) //四带一
{
int num4,num1,Pnum4,Pnum1;
for(int i=1;i<14;i++)
{
if(card[i]==0) continue;
if(card[i]==4) num4=i;
else if(card[i]==1) num1=i;
else if(card[i]==5)
{
num4=i,num1=i;
break;
}
}
for(int i=1;i<14;i++)
{
if(p.card[i]==0) continue;
if(p.card[i]==4) Pnum4=i;
else if(p.card[i]==1) Pnum1=i;
else if(p.card[i]==5)
{
Pnum4=Pnum1=i;
break;
}
}
if(num4!=Pnum4) return num4>Pnum4;
if(num1!=Pnum1) return num1>Pnum1;
return name<p.name;
}
if(Ptype==7)
{
int start,Pstart;
for(int i=1;i<14;i++)
if(card[i]==1)
{
start=i;
break;
}
for(int i=1;i<14;i++)
if(p.card[i]==1)
{
Pstart=i;
break;
}
if(start!=Pstart) return start>Pstart;
return name<p.name;
}
if(Ptype==8)
return name<p.name;
}
};
int cnt[6];
const int inf=1e5+10;
player play[inf]; //存储玩家
void clac_type(player& p)
{
string s=p.pai;
int len=s.length();
for(int i=1;i<14;i++)
p.card[i]=0;
int differ=0,phao;
for(int i=0;i<6;i++)
cnt[i]=0;
for(int i=0;i<len;i++)
{
if(s[i]!='1')
{
phao=cfind(s[i]);
if(p.card[phao]==0) differ++;
p.card[phao]++;
}
else //如果是1
{
if(p.card[10]==0) differ++;
p.card[10]++;
i++;
}
}
if(differ==5)
{
if(p.card[1]==1&&p.card[10]==1&&p.card[11]==1&&p.card[12]==1&&p.card[13]==1)
{
p.Ptype=8;
return;
}
for(int i=1;i<14;i++)
{
if(p.card[i]==1)
{
for(int j=i+1;j<i+5;j++)
if(p.card[j]!=1)
{
p.Ptype=1;
return;
}
p.Ptype=7;
return;
}
}
}
for(int i=1;i<14;i++)
cnt[p.card[i]]++;
//如果是炸弹
if(cnt[4]==1||cnt[5]==1) //炸弹
{
p.Ptype=6;
return;
}
if(cnt[3]==1&&cnt[2]==1) //三带二
{
p.Ptype=5;
return;
}
if(cnt[3]==1&&cnt[1]==2)
{
p.Ptype=4;
return;
}
if(cnt[2]==2) //两对
{
p.Ptype=3;
return;
}
if(cnt[1]==3) //一对
{
p.Ptype=2;
return;
}
}
void getAns()
{
for(int i=0;i<n;i++)
clac_type(play[i]);
sort(play,play+n); //排序
for(int i=0;i<n;i++)
cout<<play[i].name<<endl;
}
int main(void)
{
while(cin>>n)
{
for(int i=0;i<n;i++)
cin>>play[i].name>>play[i].pai;
getAns();
}
return 0;
}