题干
扑克游戏规则如下:
所有扑克牌只按数字来算大小,忽略花色。
每张扑克牌的大小由一个值表示。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 张牌的情况。要求输出一个排行榜。排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况
对于每组测试数据,输出 n 行,即这次全场人的排名
sample input:
3
DongDong AAA109
ZJM 678910
Hrz 678910
sample output:
Hrz
ZJM
DongDong
思路:
- 利用结构体来对每个人拿到的手牌进行记录
- 观察题目所给的判断条件,首先应该根据牌型进行排位,利用score记录,score越大越在前面
- 如果牌型中某些标志性牌面相同大小则对比剩余牌的大小,所以定义tot记录手牌的总大小
- 如果都相同则比较选手的字典序,通过char型数组记录名字只需要一位位进行比较即可
- 利用三个数组two,three,four来记录手中的牌是否有对子,三张相同和四张相同,数组的第一个元素用01来表示是否具有该种牌型,后面的元素用来记录该牌型的大小。由于需要比较大小,所以在记录牌面的时候要从大到小进行记录
- 首先记录每一个选手手中的牌,将牌面处理成数字进行存储,记录牌的数量并利用函数给出当前的牌型判断;对于10来说由于读入时10占两位并且只有10的开头是1,所以见到1则忽略掉后一位可以进行10的读入;如果遇到有1 有10 的题目,则需要在读入1的时候判断后面一位是不是0
- 记录完毕后进行排序,然后依次输出名字
- 需要注意的是要用多组的数据进行测试,因为判断条件很多,所以容易出现错误,我的WA就是因为一个数组的元素取错 + 少写了一个等号导致 tot 没有正常计算,可以自己多出数据进行测试。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+1;
struct card
{
char name[11];
char cards[20];
int score;//分数
int tot;//牌面大小
int two[3];//无对;一对;两对;如果有的话表示是那一对
int three[2];//没有;有三张相同的牌
int four[2];//没有,有四张相同的牌
}poker[N];
bool cmp(card a, card b)
{
if(a.score!=b.score)
return a.score > b.score;
else if(a.score==b.score)
{
if(a.score==1)//大牌,比牌的大小总和
{
if(a.tot!=b.tot)
return a.tot>b.tot;
}
else if(a.score==2)//对子,先比对子大小再比剩下牌的综合
{
if(a.two[1]!=b.two[1])
return a.two[1]>b.two[1];
else if(a.tot!=b.tot)
return a.tot>b.tot;
}
else if(a.score==3)//两对,先比大队子再小对子再大小
{
if(a.two[1]!=b.two[1])
return a.two[1]>b.two[1];
else if(a.two[2]!=b.two[2])
return a.two[2]>b.two[2];
else if(a.tot !=b.tot)
return a.tot>b.tot;
}
else if(a.score==4)//三个,先比三个大小再比两张综合
{
if(a.three[1]!=b.three[1])
return a.three[1]>b.three[1];
else if(a.tot!=b.tot)
return a.tot>b.tot;
}
else if(a.score==5)//三代二,先比三个在比两个
{
if(a.three[1]!=b.three[1])
return a.three[1]>b.three[1];
else if(a.tot!=b.tot)
return a.tot>b.tot;
}
else if(a.score==6)//炸弹先比四个在比一个
{
if(a.four[1]!=b.four[1])
return a.four[1]>b.four[1];
else if(a.tot!=b.tot)
return a.tot>b.tot;
}
else if(a.score==7)//顺子比顺子大小
{
if(a.tot!=b.tot)
return a.tot>b.tot;
}
}
//如果都一样,开始比名字的字典序
int la=sizeof(a.name);
int lb=sizeof(b.name);
int len=min(la,lb);
for(int i=0;i<len;i++)
{
if(a.name[i]!=b.name[i])
return a.name[i]<b.name[i];
}
if(la<lb) return true;
return false;
}
void give(int x)
{
int count=0;
int temp[15];
memset(temp,0,sizeof(temp));
while(count<strlen(poker[x].cards))
{
if(poker[x].cards[count]>='2'&&poker[x].cards[count]<='9')
temp[poker[x].cards[count]-'0']++;
else
{
if(poker[x].cards[count]=='1')
{
temp[10]++;
count++;
}
if(poker[x].cards[count]=='A')
temp[1]++;
if(poker[x].cards[count]=='J')
temp[11]++;
if(poker[x].cards[count]=='Q')
temp[12]++;
if(poker[x].cards[count]=='K')
temp[13]++;
}
count++;
}
if(temp[1]&&temp[10]&&temp[11]&&temp[12]&&temp[13])
{
poker[x].score=8;
return;
}
for(int i=1;i<=13;i++)
{
if(temp[i])
{
for(int j=1;j<=temp[i];j++)//就是这里,少个=直接没算tot
poker[x].tot+=i;
}
}
for(int i=13;i>=1;i--)//倒着取保证前者大
{
if(temp[i]==4)
{
poker[x].four[0]=1;
poker[x].four[1]=i;
poker[x].score=6;
return;
}
if(temp[i]==3)
{
poker[x].three[0]=1;
poker[x].three[1]=i;
//这里还要继续向下判断是哪一个类型
}
if(temp[i]==2)
{
poker[x].two[0]++;
if(poker[x].two[0]==1)
poker[x].two[1]=i;
else
{
poker[x].two[2]=i;
poker[x].score=3;
return;
}
}
}
for(int i=1;i<=9;i++)
{
if(temp[i]&&temp[i+1]&&temp[i+2]&&temp[i+3]&&temp[i+4])
{
poker[x].score=7;
return;
}
}
if(poker[x].two[0]==1&&poker[x].three[0]==1)
{
poker[x].score=5;
return;
}
if(poker[x].two[0]==1)
{
poker[x].score=2;
return;
}
if(poker[x].three[0]==1)
{
poker[x].score=4;
return;
}
poker[x].score=1;
}
void init(int i)
{
memset(poker[i].two,0,sizeof(poker[i].two));
memset(poker[i].three,0,sizeof(poker[i].three));
memset(poker[i].four,0,sizeof(poker[i].four));
poker[i].tot=0;
poker[i].score=0;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
init(i);
scanf("%s %s",&poker[i].name,&poker[i].cards);
give(i);
}
sort(poker+1,poker+n+1,cmp);
for(int i=1;i<=n;i++)
printf("%s\n",poker[i].name);
}
return 0;
}