题意:
最近,东东沉迷于打牌。所以他找到 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。请你告诉东东,全场人的排名。
思路:
建立一个结构体pai,用于记录拿牌者姓名、牌型,以及各级比较值cmp1、cmp2、cmp3,用于在牌型相同时,进行比较。
在输入每个人的牌之后,先把不同的牌分别用不同数字进行表示,其中,A用1记录,JQK分别用11、12、13记录。
然后给五张牌进行排序,之后即可判断牌型大小,以及各级比较值的大小,然后对所有人的牌进行排序即可得到答案。
代码:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
struct pai {
string name;
int type;
int cmp1;
int cmp2;
int cmp3;
pai() { cmp1 = cmp2 = cmp3 = 0; }
bool operator < (const pai& ca) const {
if (type != ca.type)
return type < ca.type;
if (cmp1 != ca.cmp1)
return cmp1 < ca.cmp1;
if (cmp2 != ca.cmp2)
return cmp2 < ca.cmp2;
if (cmp3 != ca.cmp3)
return cmp3 < ca.cmp3;
return name > ca.name;
}
};
pai p[100010];
int main()
{
int n;
while (scanf("%d", &n) != EOF) {
//输入并初始化
for (int i = 0; i < n; i++) {
cin >> p[i].name;
string str;
cin >> str;
int j = 0, num = 0;
int c[60];
int len = (int)str.size();
while (j < len) {
if (str[j] == '1') {
c[num] = 10;
num++;
j = j + 2;
continue;
}
if (str[j] > '1' && str[j] <= '9') {
c[num] = str[j] - '0';
num++;
j++;
continue;
}
if (str[j] == 'A') {
c[num] = 1;
num++;
j++;
continue;
}
if (str[j] == 'J') {
c[num] = 11;
num++;
j++;
continue;
}
if (str[j] == 'Q') {
c[num] = 12;
num++;
j++;
continue;
}
if (str[j] == 'K') {
c[num] = 13;
num++;
j++;
continue;
}
}
sort(c, c + 5);
int sum = c[0] + c[1] + c[2] + c[3] + c[4];
if (c[0] == 1 && c[1] == 10 && c[2] == 11 && c[3] == 12 && c[4] == 13) {
//龙顺
p[i].type = 8;
}
else if (c[1] == c[0] + 1 && c[2] == c[0] + 2 && c[3] == c[0] + 3 && c[4] == c[0] + 4) {
//顺子
p[i].type = 7;
p[i].cmp1 = c[4];
}
else if (c[0] == c[3] || c[1] == c[4]) {
//炸弹
p[i].type = 6;
p[i].cmp1 = c[1];
p[i].cmp2 = sum;
}
else if ((c[0] == c[2] && c[3] == c[4]) || (c[0] == c[1] && c[2] == c[4])) {
//三带二
p[i].type = 5;
p[i].cmp1 = c[2];//c[2]一定是三张牌的值
p[i].cmp2 = sum;//三张牌一样,就判断sum
}
else if (c[0] == c[2] || c[1] == c[3] || c[2] == c[4]) {
//三不带
p[i].type = 4;
p[i].cmp1 = c[2];//c[2]一定是三张牌的值
p[i].cmp2 = sum;//三张牌一样,就判断sum
}
else if ((c[0] == c[1] && c[2] == c[3]) || (c[0] == c[1] && c[3] == c[4]) || (c[1] == c[2] && c[3] == c[4])) {
//两个对
p[i].type = 3;
p[i].cmp1 = c[3];//c[3]一定是大对的值
p[i].cmp2 = c[1];//c[1]一定是小对的值
p[i].cmp3 = sum;//大小对都一样,那就判断sum
}
else if (c[0] == c[1] || c[1] == c[2] || c[2] == c[3] || c[3] == c[4]) {
//一个对
p[i].type = 2;
int t;
for (int k = 0; k < 4; k++) {
if (c[k] == c[k + 1]) {
t = k;
}
}
p[i].cmp1 = c[t];
p[i].cmp2 = sum;
}
else {
p[i].type = 1;
p[i].cmp1 = sum;
}
}
sort(p, p + n);
for (int i = n - 1; i >= 0; i--) {
cout << p[i].name << endl;
}
}
}