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;
}
}