一、题目描述
题面
最近,东东沉迷于打牌。所以他找到 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
二、思路概述
- 根据输入的名字和牌面,将牌面转换为相应的数字,再处理。
- 根据五张牌的大小,来判断是什么牌面,并设置相应的表示牌面的值type,和其他可以判断大小的关键字。
- 设置sort函数,根据题目要求,先按牌面大小,再按关键字级别大小排序,直到按照名字的字典序排序
三、完整代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <string>
using namespace std;
char ca[13]={'A','2','3','4','5','6','7','8','9','1','J','Q','K'};
struct pk
{
string name;
string card;//牌面
//int size[5];//五张牌的大小
int type;//type表明了牌型
int x,y,z;//用于不同牌型的数字大小
//x、y、z的等级不同
pk(){type=x=y=z=0;}
/*pk(string n,int t,int xx,int yy,int zz)
{
name=n;
type=t;
x=xx;
y=yy;
z=zz;
}*/
}p[100010];
int cmp(pk p1,pk p2)
{
if(p1.type!=p2.type )
{
return p1.type>p2.type;//降序 ,待定
}
else
{
if(p1.x!=p2.x)
{
return p1.x>p2.x;//降序
}
else
{
if(p1.y!=p2.y)
{
return p1.y>p2.y;
}
else
{
if(p1.z!=p2.z)
{
return p1.z>p2.z;
}
else
{
return p1.name < p2.name ? 1 : 0;//升序
}
}
}
}
}
bool shun(int sz[], int* a) {//龙顺
bool shun=true;
for(int i=1;i<5;i++)
{
if(sz[i]!=sz[0]+i)shun=false;
}
if(shun==true)
{
a[0]=7;
a[1]=sz[4];//x里放顺子里的最大值
a[2]=a[3]=0;
//pp.y=pp.z=0;
//cout<<"shun"<<endl;
return true;
}
return false;
}
bool longsh(int sz[], int* a) {//顺子
if (sz[0] == 0 && sz[1] == 9 && sz[2] == 10 && sz[3] == 11 && sz[4] == 12) {
a[0] = 8; a[1] = 0; a[2] = 0; a[3] = 0;
return 1;
}
return 0;
}
bool boom(int sz[], int* a) {//炸弹
if (sz[0] == sz[1] && sz[1] == sz[2] && sz[2] == sz[3]) {
a[0] = 6; a[1] = sz[0]; a[2] = sz[4]; a[3] = 0;
return 1;
}
if (sz[4] == sz[1] && sz[1] == sz[2] && sz[1] == sz[3]) {
a[0] = 6; a[1] = sz[4]; a[2] = sz[0]; a[3] = 0;
return 1;
}
return 0;
}
bool threetotwo(int sz[], int* a) {//三带二
if (sz[0] == sz[1] && sz[1] == sz[2] && sz[3] == sz[4]) {
a[0] = 5; a[1] = sz[0]; a[2] = sz[4]; a[3] = 0;
return 1;
}
if (sz[0] == sz[1] && sz[2] == sz[3] && sz[2] == sz[4]) {
a[0] = 5; a[1] = sz[4]; a[2] = sz[0]; a[3] = 0;
return 1;
}
return 0;
}
bool three(int sz[], int* a) {//三个
if (sz[0] == sz[1] && sz[1] == sz[2]) {
a[0] = 4; a[1] = sz[0]; a[2] = sz[3] + sz[4]; a[3] = 0;
return 1;
}
if (sz[3] == sz[1] && sz[1] == sz[2]) {
a[0] = 4; a[1] = sz[1]; a[2] = sz[0] + sz[4]; a[3] = 0;
return 1;
}
if (sz[3] == sz[4] && sz[3] == sz[2]) {
a[0] = 4; a[1] = sz[2]; a[2] = sz[1] + sz[0]; a[3] = 0;
return 1;
}
return 0;
}
bool twotwo(int sz[], int* a) {//两对
if (sz[0] == sz[1] && sz[2] == sz[3]) {
if (sz[0] > sz[2]) {
a[0] = 3; a[1] = sz[0]; a[2] = sz[2]; a[3] = sz[4];
}
else {
a[0] = 3; a[1] = sz[2]; a[2] = sz[0]; a[3] = sz[4];
}
return 1;
}
if (sz[1] == sz[2] && sz[3] == sz[4]) {
if (sz[3] > sz[2]) {
a[0] = 3; a[1] = sz[3]; a[2] = sz[2]; a[3] = sz[0];
}
else {
a[0] = 3; a[1] = sz[2]; a[2] = sz[3]; a[3] = sz[0];
}
return 1;
}
if (sz[0] == sz[1] && sz[3] == sz[4]) {
if (sz[1] > sz[3]) {
a[0] = 3; a[1] = sz[1]; a[2] = sz[3]; a[3] = sz[2];
}
else {
a[0] = 3; a[1] = sz[3]; a[2] = sz[1]; a[3] = sz[2];
}
return 1;
}
return 0;
}
bool two(int sz[], int* a) {//对子
if (sz[0] == sz[1]) {
a[0] = 2; a[1] = sz[1]; a[2] = sz[2] + sz[3] + sz[4]; a[3] = 0;
return 1;
}
if (sz[1] == sz[2]) {
a[0] = 2; a[1] = sz[1]; a[2] = sz[0] + sz[3] + sz[4]; a[3] = 0;
return 1;
}
if (sz[2] == sz[3]) {
a[0] = 2; a[1] = sz[2]; a[2] = sz[1] + sz[0] + sz[4]; a[3] = 0;
return 1;
}
if (sz[3] == sz[4]) {
a[0] = 2; a[1] = sz[3]; a[2] = sz[2] + sz[1] + sz[0]; a[3] = 0;
return 1;
}
return 0;
}
bool big(int sz[], int* a) {
a[0] = 1; a[1] = sz[0] + sz[1] + sz[3] + sz[2] + sz[4];
a[2] = 0; a[3] = 0;
return 1;
}
int* cont(int sz[]) {
sort(sz, sz + 5);
int* a = new int[4];
if (longsh(sz, a)) { return a; }
if (shun(sz, a)) { return a; }
if (boom(sz, a)) { return a; }
if (threetotwo(sz, a)) { return a; }
if (three(sz, a)) { return a; }
if (twotwo(sz, a)) { return a; }
if (two(sz, a)) { return a; }
big(sz, a);
return a;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
string na;
char b;
int siz[5];//5张牌的大小
cin >> na;
for (int j = 0; j < 5; j++)
{
cin >> b;
for (int k = 0; k < 13; k++)
{
if (b == ca[k])
{
siz[j] = k; //比实际的数值小一个
if (b == '1') { scanf("%c", &b); }//把0拿进来
break;
}
}
}
int* a = cont(siz);
p[i].name = na;
p[i].type = a[0]; p[i].x = a[1];
p[i].y = a[2]; p[i].z = a[3];
//cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
}//输入n个人和他们的牌
sort(p, p + n,cmp);
for (int i = 0; i < n; i++)
{
cout << p[i].name << endl;
}
return 0;
}