题目描述
最近,东东沉迷于打牌。所以他找到 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。请你告诉东东,全场人的排名
输入
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。
输出
对于每组测试数据,输出 n 行,即这次全场人的排名。
样例输入
3
DongDong AAA109
ZJM 678910
Hrz 678910
样例输出
Hrz
ZJM
DongDong
题目分析
本题是打牌模拟,依然是老套路:定义结构体+map映射点数+定牌型+sort+cmp比较函数
首先建立输入与可比较数据类型(即int)的映射,然后读入每个人的信息(名字+手牌),然后对手牌进行排序,并进行定牌型操作。通过之前定义好的cmp函数对这n个人进行排序,再输出结果。
要记得每次输出后清空结构体,手动适配即可,struct用memset会出现可怕的结果。
注意
不能用while ((temp=getchar())!='\n')
判断一行的结束,因为最后一条数据没有回车,会RE。慎用getchar()和getline(),除非不得不用。
代码
#define _ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include <bits/stdc++.h>
//#include <iostream>
//#include<algorithm>
using namespace std;
map<char,int> poker;
struct node
{//每个人
string name;
vector<int> mypoker;
int label;//牌型
int boom[2];//炸弹大小和剩余牌
int threePtwo[2];//3+2
int three[2];//3+(1+1)
int twoPtwo[3];//2+2+1
int two[2];//2+(1+1+1)
int one;//5*1
}stu[100009];
bool cmp(node a,node b)
{
if(a.label!=b.label)return a.label>b.label;
else if(a.label==8)return a.name<b.name;
else if(a.label==7)
{
if(a.mypoker[4]!=b.mypoker[4])return a.mypoker[4]>b.mypoker[4];
else return a.name<b.name;
}
else if(a.label==6)
{
if(a.boom[0]!=b.boom[0])return a.boom[0]>b.boom[0];
else if(a.boom[1]!=b.boom[1])return a.boom[1]>b.boom[1];
else return a.name<b.name;
}
else if(a.label==5)
{
if(a.threePtwo[0]!=b.threePtwo[0])return a.threePtwo[0]>b.threePtwo[0];
else if(a.threePtwo[1]!=b.threePtwo[1])return a.threePtwo[1]>b.threePtwo[1];
else return a.name<b.name;
}
else if(a.label==4)
{
if(a.three[0]!=b.three[0])return a.three[0]>b.three[0];
else if(a.three[1]!=b.three[1])return a.three[1]>b.three[1];
else return a.name<b.name;
}
else if(a.label==3)
{
if(a.twoPtwo[0]!=b.twoPtwo[0])return a.twoPtwo[0]>b.twoPtwo[0];
else if(a.twoPtwo[1]!=b.twoPtwo[1])return a.twoPtwo[1]>b.twoPtwo[1];
else if(a.twoPtwo[2]!=b.twoPtwo[2])return a.twoPtwo[2]>b.twoPtwo[2];
else return a.name<b.name;
}
else if(a.label==2)
{
if(a.two[0]!=b.two[0])return a.two[0]>b.two[0];
else if(a.two[1]!=b.two[1])return a.two[1]>b.two[1];
else return a.name<b.name;
}
else if(a.label==1)
{
if(a.one!=b.one)return a.one>b.one;
else return a.name<b.name;
}
}
int main()
{
// _;
// freopen("in.txt","r",stdin);
poker['A']=1;
poker['2']=2;
poker['3']=3;
poker['4']=4;
poker['5']=5;
poker['6']=6;
poker['7']=7;
poker['8']=8;
poker['9']=9;
poker['1']=10;//注意
poker['J']=11;
poker['Q']=12;
poker['K']=13;
int n;//组数
while (cin>>n)
{
// getchar();//这里注意!!!cin后的回车留在缓冲区
//整理手牌
for (int i = 0; i < n; i++)
{
// char temp;
int temp_num;
string str_temp;
// while ((temp=getchar())!=' ')
// {
// stu[i].name.push_back(temp);
// }
//最后一组数据的时候没有回车!不能通过这个终止条件判断结束!
// while ((temp=getchar())!='\n')
// {
// if(temp=='1')getchar();//吞10的0
// temp_num=poker[temp];
// stu[i].mypoker.push_back(temp_num);
// }
cin>>stu[i].name;
cin>>str_temp;
for (int j = 0; j < str_temp.length(); j++)
{
stu[i].mypoker.push_back(poker[str_temp[j]]);
if(str_temp[j]=='1')j++;//处理10的0, 长长记性:这里是'1'而非1!!!
}
// getchar();//吞掉最后的回车键,但是也不对!因为不知道有没有下一组数据,会死循环
sort(stu[i].mypoker.begin(),stu[i].mypoker.end());
if(stu[i].mypoker[0]==1 &&stu[i].mypoker[1]==10 &&stu[i].mypoker[2]==11&&stu[i].mypoker[3]==12&&stu[i].mypoker[4]==13)
{
stu[i].label=8;
continue;
}
if(stu[i].mypoker[4]==stu[i].mypoker[3]+1&&stu[i].mypoker[3]==stu[i].mypoker[2]+1&&stu[i].mypoker[2]==stu[i].mypoker[1]+1&&stu[i].mypoker[1]==stu[i].mypoker[0]+1)
{
stu[i].label=7;
continue;
}
int box[14];//牌数箱子
int mx_temp=0;
memset(box,0,sizeof(box));
for(int num=0;num<5;num++)
{
box[stu[i].mypoker[num]]++;
mx_temp=max(box[stu[i].mypoker[num]],mx_temp);
}
if(mx_temp==4)
{
for(int j=1;j<=13;j++)
{
if(box[j]==4)stu[i].boom[0]=j;
if(box[j]==1)stu[i].boom[1]=j;
}
stu[i].label=6;
continue;
}
if(mx_temp==3)
{//i和j不要混!!!wa的时候检查一些变量是否互相干扰!!!
for(int j=1;j<=13;j++)
{
if(box[j]==3){stu[i].threePtwo[0]=j;stu[i].three[0]=j;}
if(box[j]==2)stu[i].threePtwo[1]=j;
if(box[j]==1)stu[i].three[1]+=j;
}
if(stu[i].threePtwo[1]!=0)stu[i].label=5;
else stu[i].label=4;
continue;
}
int two1=0,two2=0;
for(int j=1;j<=13;j++)
{
if(box[j]==2)
{
if(two1!=0)two2=j;
else two1=j;
}
}
if(two1!=0&&two2!=0)
{
if(two1<two2)swap(two1,two2);
for(int j=1;j<=13;j++)if(box[j]==1)stu[i].twoPtwo[2]=j;
stu[i].twoPtwo[0]=two1;
stu[i].twoPtwo[1]=two2;
stu[i].label=3;
continue;
}
if(two1!=0&&two2==0)
{
for(int j=1;j<=13;j++)
if(box[j]==1)stu[i].two[1]+=j;
stu[i].two[0]=two1;
stu[i].label=2;
continue;
}
for(int num=0;num<5;num++)stu[i].one+=stu[i].mypoker[num];
stu[i].label=1;
}
//排序并输出
sort(stu,stu+n,cmp);
for(int i=0;i<n;i++)
cout<<stu[i].name<<endl;
//清空以备后续使用
for(int i = 0; i < n; i++)
{
stu[i].name= "";
// stu[i].name.clear();
while (!stu[i].mypoker.empty())
{
stu[i].mypoker.pop_back();
}
stu[i].label=0;
stu[i].boom[0]=0;stu[i].boom[1]=0;
stu[i].threePtwo[0]=0;stu[i].threePtwo[1]=0;
stu[i].three[0]=0;stu[i].three[1]=0;
stu[i].twoPtwo[0]=0;stu[i].twoPtwo[1]=0;stu[i].twoPtwo[2]=0;
stu[i].two[0]=0;stu[i].two[1]=0;
stu[i].one=0;
}
}
return 0;
}