SDU程序设计思维Week9 B-东东学打牌

SDU程序设计思维Week9

B-东东学打牌

Description

在这里插入图片描述在这里插入图片描述

Sample

Input:
3
DongDong AAA109
ZJM 678910
Hrz 678910

Output:
Hrz
ZJM
DongDong

Idea

题意:根据n个人的一手牌,判断牌型,然后排序,对8种牌型判断分而治之

1. 初始化
person类记录每个人的姓名、一手牌以及值
record类相当于一个带计数的set,同时记录每个人手牌中每张牌出现的次数

获得每个人的姓名和一手牌,把五张牌的字符串都转换成对应的数字,并升序排序五张牌方便后续的牌型判断
对每个人的一手牌判断真实的值,然后根据规定的比较规则,把n个人进行排序,比较时首先比较两者的value,value代表牌型,下面我将根据value从大到小进行说明,具体判断和比较规则如下

2. 龙顺:
5张牌转化成数字并排序后,只需要从左到右判断是否等于1,10,11,12,13,同为龙顺,则字典序最小优先

3. 顺子
5张牌转化成数字并排序后,只需要判断从左到右是否递增1,同为顺子则比较两副牌最小牌的大小,仍相同则字典序最小优先

4. 炸弹、三带二、三个、两对、对子、大牌
上述6种牌型从左到右value递减,但由于判断牌的值的方式类似,可以一起判断
用record类记录每副牌出现过的不同的牌以及对应次数
一副牌中出现次数最多为4时判断为炸弹,两副牌同为炸弹时,先比较炸弹大小再比较单牌大小,最后比较字典序
一副牌中出现次数最多为3且总共出现过的不同牌数为2时判断为三带二,两副牌同为三带二时,先比较“三”大小再比较“二”大小,最后比较字典序
一副牌中出现次数最多为3且总共出现过的不同牌数为3时判断为三个,两副牌同为三个时,先比较“三”大小再比较两张单牌和的大小,最后比较字典序
一副牌中出现次数最多为2且总共出现过的不同牌数为3时判断为两对,两副牌同为两对时,先比较大对子的大小再比较小对子的大小然后比较单盘的大小,最后比较字典序
一副牌中出现次数最多为2且总共出现过的不同牌数为4时判断为对子,两副牌同为对子时,先比较对子的大小再比较三张单牌和的大小,最后比较字典序
一副牌中出现次数最多为1且总共出现过的不同牌数为5时判断为大牌,两副牌同为大牌时,比较五张牌和的大小,最后比较字典序

5. 根据上述规则排序后,就能得到n个人的最终排名

Summary

这题也是复杂的模拟题,思想与A题类似,命令的判断变成了牌型的判断,同样对每种牌型分而治之,再寻求牌型之间的联系以降低时间复杂度,例如炸弹、三带二、三个、两对、对子、大牌的协同判断
注意!!JQK在ASCII表中不是连续的,因为这个WA了!!

Codes

#include<iostream>
#include<algorithm>
#include <string>
#include<cstring>
using namespace std;

struct person {
	string s1;
	int s2[5];
	int value;
	int two[4];
	int three[3];
	int four[2];
	int one;
}p[100100];

struct record {
	int m=-1;
	int n=0;
	bool operator<(record &r) {
		if(n!=r.n)return n > r.n;
		else return m > r.m;
	}
};

int n;

bool type8(person &x) {
	return x.s2[0] == 1 && x.s2[1] == 10 && x.s2[2] == 11 && x.s2[3] == 12 && x.s2[4] == 13;
}

bool type7(person &x) {
	return x.s2[0]+1 == x.s2[1] && x.s2[1] + 1 == x.s2[2] && x.s2[2] + 1 == x.s2[3] && x.s2[3] + 1 == x.s2[4] ;
}


bool great(int a, int b) {
	return a > b;
}

int judge(person &x) {

	if (type8(x)) { return 8; }
	else if (type7(x)) { return 7; }
	else {
		record r[5];
		int k = 1;
		int sum = x.s2[0];
		r[0].m = x.s2[0];
		r[0].n++;
		for (int i = 1; i < 5; i++) {
			for (int j = 0; j < k; j++) {
				if (x.s2[i] == r[j].m) {
					r[j].n++; break;
				}
				if (j == k - 1) { r[k].m=x.s2[i]; k++; }
			}
			sum += x.s2[i];
		}

		sort(r, r + k);
		int max1 = r[0].n;

		if (k == 2 && max1 == 4) { x.four[0] = r[0].m, x.four[1] = r[1].m; return 6; }
		else if (k == 2 && max1 == 3) { x.three[0] = r[0].m, x.three[1] = r[1].m; return 5; }
		else if (k == 3 && max1 == 2) { x.two[0] = r[0].m, x.two[1] = r[1].m, x.two[2] = r[2].m; return 3; }
		else if (k == 3 && max1 == 3) { x.three[0] = r[0].m, x.three[1] = r[1].m, x.three[2] = r[2].m; return 4; }
		else if (k == 4 && max1 == 2){ x.two[0] = r[0].m, x.two[1] = r[1].m, x.two[2] = r[2].m,x.two[3]=r[3].m; return 2;}
		else if (k == 5) { x.one = sum; return 1; }
	}
}


bool cmp(person &x,person &y) {
	if (x.value != y.value)return x.value > y.value;
	else {
		int t = x.value;
		if (t == 8)return x.s1 < y.s1;
		else if (t == 7) {
			return x.s2[0] != y.s2[0] ? x.s2[0] > y.s2[0]:x.s1 < y.s1;
		}
		else if(t==6){
			if (x.four[0] != y.four[0])return x.four[0] > y.four[0];
			else {
				if(x.four[1]!= y.four[1])return x.four[1] > y.four[1];
				else return x.s1 < y.s1;
			}

		}
		else if (t == 5) {
			if (x.three[0] != y.three[0])return x.three[0] > y.three[0];
			else {
				if (x.three[1] != y.three[1])return x.three[1] > y.three[1];
				else return x.s1 < y.s1;
			}
		}
		else if (t == 4) {
			if (x.three[0] != y.three[0])return x.three[0] > y.three[0];
			else {
				int x1 = x.three[1] + x.three[2];
				int y1 = y.three[1] + y.three[2];
				if ( x1!=y1 )return x1 > y1;
				else return x.s1 < y.s1;
			}
		}
		else if (t == 3) {
			if (x.two[0] != y.two[0])return x.two[0] > y.two[0];
			else if(x.two[1] != y.two[1])return x.two[1] > y.two[1];
			else {
				if (x.two[2] != y.two[2])return x.two[2] > y.two[2];
				else return x.s1 < y.s1;
			}
		}
		else if (t == 2) {
			if (x.two[0] != y.two[0])return x.two[0] > y.two[0];
			else {
				int x1 = x.two[1] + x.two[2]+x.two[3];
				int y1 = y.two[1] + y.two[2]+y.two[3];
				if (x1 != y1)return x1 > y1;
				else return x.s1 < y.s1;
			}
		}
		else if (t == 1) {
			if (x.one != y.one)return x.one > y.one;
			else return x.s1 < y.s1;

		}

	}

}

void init() {
	for (int i = 0; i <= n; i++) {
		p[i].one = 0;
		memset(p[i].four, 0, sizeof(p[i].four));
		memset(p[i].three, 0, sizeof(p[i].three));
		memset(p[i].two, 0, sizeof(p[i].two));
		p[i].value = 0;
	}
}

int main() 
{
	
	while (scanf("%d",&n)!=EOF) {

		init();
		for (int i = 0; i < n; i++) {
			string s2;
			cin >> p[i].s1 >> s2;
			int m = s2.size();

			int num = 0;
			for (int k = 0; k < m; k++) {
				if (s2[k] == 'A')p[i].s2[num++] = 1;
				else if (s2[k] == 'J' )p[i].s2[num++] = s2[k] - 'J' + 11;
				else if (s2[k] == 'Q')p[i].s2[num++] = s2[k] - 'Q' + 12;
				else if (s2[k] == 'K')p[i].s2[num++] = s2[k] - 'K' + 13;
				else if (s2[k] == '2' || s2[k] == '3' || s2[k] == '4' || s2[k] == '5' || s2[k] == '6' || s2[k] == '7' || s2[k] == '8' || s2[k] == '9')p[i].s2[num++] = s2[k] - '0';
				else if (s2[k] == '1' && (k != m - 1) && s2[k + 1] == '0') { p[i].s2[num++] = 10; k++; }

			}

			sort(p[i].s2, p[i].s2 + 5);
			p[i].value = judge(p[i]);

		}
		
		sort(p, p + n,cmp);

		for (int i = 0; i < n; i++)
			cout << p[i].s1 << endl;


	}


}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值