week9 B- 东东学打牌

一、题目描述

题面
最近,东东沉迷于打牌。所以他找到 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值