【B - 东东学打牌】

题意:

游戏规则:
所有扑克牌只按数字来算大小,忽略花色。
每张扑克牌的大小由一个值表示。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 张牌不同,其值不同。下面依次列举了这手牌的形成规则:
1.大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。
2.对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 “对子” 的大小,如果 α 和 β 的 “对子” 大小相等,那么比较剩下 3 张牌的总和。
3.两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。
4.三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 “三个”,比较这个 “三个” 的大小,如果 α 和 β 的 “三个” 大小相等,那么比较剩下 2 张牌的总和。
5.三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 “三带二”,先比较它们的 “三个” 的大小,如果相等,再比较 “对子” 的大小。
6.炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 “炸弹”,比较 “炸弹” 的大小,如果相等,比较剩下那张牌的大小。
7.顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 “顺子”,直接比较两个顺子的最大值。
8.龙顺:5 张牌分别为 10、J、Q、K、A。
输出一个排行榜,排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。

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 Input:

Hrz
ZJM
DongDong

思路:

定义结构体peop存储每个人的信息

  1. deal() 利用map对应每个字符,处理每个人的牌所在字符串,将五张牌存在数组中。
  2. mark() 先给五张牌排序,然后利用牌的特点判定属于哪个值。因为值相同时,要比较其他条件,所以结构体中p1,p2,p3分别代表第一二三条件,同时为其赋值。
  3. com() 重定义比较函数,值不相同时,值大的获胜。值相同时,先判断值是多少,然后根据这个值的条件数依次比较这两个人的条件。如果都相同则调用字典序比较函数。

代码:

#include<iostream>
#include<algorithm>
#include<string>
#include<map>
using namespace std;
const int N = 1e5 + 10;
map<char, int> siz;
struct peop
{
	string nam;
	string pa;
	int judge;//牌的类型
	int pai[6];//存储五张牌
	int p1;//第一比较条件
	int p2;//第二比较条件
	int p3;
	peop(int q1 = 0, int q2 = 0, int q3 = 0)
	{
		p1 = q1;
		p2 = q2;
		p3 = q3;
	}
};
peop e[N];
void mark(int x)
{
	sort(e[x].pai + 1, e[x].pai + 6);
	int a = e[x].pai[1], b = e[x].pai[2], c = e[x].pai[3], d = e[x].pai[4], f = e[x].pai[5];
	if (a == 1 && b == 10 && c == 11 && d == 12 && f == 13)
		e[x].judge = 8;
	else if (b - a == 1 && c - b == 1 && d - c == 1 && f - d == 1)
	{
		e[x].judge = 7;
		e[x].p1 = f;
	}
	else if (a == b && b == c && c == d)
	{
		e[x].judge = 6;
		e[x].p1 = a;
		e[x].p2 = f;
	}
	else if (b == c && c == d && d == f)
	{
		e[x].judge = 6;
		e[x].p1 = b;
		e[x].p2 = a;
	}
	else if (a == b && b == c && d == f)
	{
		e[x].judge = 5;
		e[x].p1 = a;
		e[x].p2 = d;
	}
	else if (a == b && c == d && d == f)
	{
		e[x].judge = 5;
		e[x].p1 = c;
		e[x].p2 = a;
	}
	else if (a == b && b == c)
	{
		e[x].judge = 4;
		e[x].p1 = a;
		e[x].p2 = d + f;
	}
	else if (b == c && c == d)
	{
		e[x].judge = 4;
		e[x].p1 = b;
		e[x].p2 = a + f;
	}
	else if (c == d && d == f)
	{
		e[x].judge = 4;
		e[x].p1 = c;
		e[x].p2 = a + b;
	}
	else if (a == b && c == d)
	{
		e[x].judge = 3;
		if (a > c)
		{
			e[x].p1 = a;
			e[x].p2 = c;
		}
		else
		{
			e[x].p1 = c;
			e[x].p2 = a;
		}
		e[x].p3 = f;
	}
	else if (a == b && d == f)
	{
		e[x].judge = 3;
		if (a > d)
		{
			e[x].p1 = a;
			e[x].p2 = d;
		}
		else
		{
			e[x].p1 = d;
			e[x].p2 = a;
		}
		e[x].p3 = c;
	}
	else if (b == c && d == f)
	{
		e[x].judge = 3;
		if (b > d)
		{
			e[x].p1 = b;
			e[x].p2 = d;
		}
		else
		{
			e[x].p1 = d;
			e[x].p2 = b;
		}
		e[x].p3 = a;
	}
	else if (a == b)
	{
		e[x].judge = 2;
		e[x].p1 = a;
		e[x].p2 = c + d + f;
	}
	else if (b == c)
	{
		e[x].judge = 2;
		e[x].p1 = b;
		e[x].p2 = a + d + f;
	}
	else if (c == d)
	{
		e[x].judge = 2;
		e[x].p1 = c;
		e[x].p2 = a + b + f;
	}
	else if (d == f)
	{
		e[x].judge = 2;
		e[x].p1 = d;
		e[x].p2 = a + b + c;
	}
	else
	{
		e[x].judge = 1;
		e[x].p1 = a + b + c + d + f;
	}
}
bool dir(string str1, string str2)//str1字典序小返回true
{
	int len1 = str1.length();
	int len2 = str2.length();
	if (len1 < len2)
		swap(len1, len2);
	for (int i = 0; i < len2; i++)
	{
		if (str1.at(i) == str2.at(i))
			continue;
		return str1.at(i) < str2.at(i);
	}
	return str1.length() < str2.length();
}
void deal(int x)
{
	int i = 0;
	string str = e[x].pa;
	int len = str.length();
	int j = 1;//标记pai的位置
	while (i < len)
	{
		if (str.at(i) == '1')
		{
			e[x].pai[j] = 10;
			i += 2;
		}
		else
		{
			e[x].pai[j] = siz.find(str.at(i))->second;
			i++;
		}
		j++;
	}
	mark(x);
}
bool com(peop a, peop b)//从大到小排序
{
	if (a.judge != b.judge)
		return a.judge > b.judge;
	else
	{
		switch (a.judge)
		{
		case 8:
			return dir(a.nam, b.nam);
			break;
		case 7:case 1:
			if (a.p1 != b.p1)return a.p1 > b.p1;
			else return dir(a.nam, b.nam);
			break;
		case 6:case 5:case 4:case 2:
			if (a.p1 != b.p1)return a.p1 > b.p1;
			else if (a.p2 != b.p2)return a.p2 > b.p2;
			else return dir(a.nam, b.nam);
			break;
		case 3:
			if (a.p1 != b.p1)return a.p1 > b.p1;
			else if (a.p2 != b.p2)return a.p2 > b.p2;
			else if (a.p3 != b.p3)return a.p3 > b.p3;
			else return dir(a.nam, b.nam);
			break;
		}
	}
}
int main()
{
	siz.insert({ 'A', 1 });
	siz.insert({ '2', 2 });
	siz.insert({ '3', 3 });
	siz.insert({ '4', 4 });
	siz.insert({ '5', 5 });
	siz.insert({ '6', 6 });
	siz.insert({ '7', 7 });
	siz.insert({ '8', 8 });
	siz.insert({ '9', 9 });
	siz.insert({ 'J', 11 });
	siz.insert({ 'Q', 12 });
	siz.insert({ 'K', 13 });
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> e[i].nam;
		cin >> e[i].pa;
		deal(i);
	}
	sort(e + 1, e + n + 1, com);
	for (int i = 1; i <= n; i++)
		cout << e[i].nam << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值