题面
最近,东东沉迷于打牌。所以他找到 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
样例输出
DongDong
ZJM
Hrz
思路
第六周模拟题 的延伸,判断手牌的类别的思路基本不变,把 5 张牌放入 map ,根据 map 的大小以及 key-value 的值即可确定类别;对于牌的大小对比,根据题意重载 < ,然后调用 sort 进行排序最后输出结果即可。
因为直接从上份代码的基础上改了改,这里的重载写得有点麻烦了…我直接把对应的map以数组的形式拷贝到了结构体里,然后两个结构体的map再进行比较,其实大可不必。在结构体内声明几个变量,分别表示牌值的加和、出现次数为4,3,2,1的牌大小,也可实现相同功能。
代码实现
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
int n,b[5];
char s1[20],s2[20];
map<char,int> mp;
struct player{
string name;
int val;
int element[5];
int c[10];
int d[15];
bool operator<(const player &s)const{
if(val==s.val){
int tot1=0,tot2=0;
for(int i=0;i<5;i++){
tot1+=element[i];
tot2+=s.element[i];
}
if(val==8)
return name<s.name;
else if(val==7){
if(element[4]!=s.element[4])
return element[4]>s.element[4];
else
return name<s.name;
}
else if(val==6){
int bomb1=c[4]==0?c[5]:c[4];
int bomb2=s.c[4]==0?s.c[5]:s.c[4];
if(bomb1!=bomb2){
return bomb1>bomb2;
}
else{
if(tot1!=tot2)
return tot1>tot2;
else
return name<s.name;
}
}
else if(val==5){
if(c[3]==s.c[3]){
if(c[2]==s.c[2])
return name<s.name;
else
return c[2]>s.c[2];
}
else
return c[3]>s.c[3];
}
else if(val==4){
if(c[3]==s.c[3]){
if(tot1!=tot2)
return tot1>tot2;
else
return name<s.name;
}
else
return c[3]>s.c[3];
}
else if(val==3){
vector<int> two1,two2;
for(int i=1;i<=13;i++){
if(d[i]==2)
two1.push_back(i);
if(s.d[i]==2)
two2.push_back(i);
}
sort(two1.begin(),two1.end());
sort(two2.begin(),two2.end());
if(two1[1]==two2[1]){
if(two1[0]==two2[0]){
if(tot1!=tot2)
return tot1>tot2;
else
return name<s.name;
}
else
return two1[0]>two2[0];
}
else
return two1[1]>two2[1];
}
else if(val==2){
if(c[2]==s.c[2]){
if(tot1!=tot2)
return tot1>tot2;
else
return name<s.name;
}
else
return c[2]>s.c[2];
}
else{
if(tot1!=tot2)
return tot1>tot2;
else
return name<s.name;
}
}
else
return val>s.val;
}
}a[100010];
int Value(string s,int cnt){
int idx=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
if(i+1>=s.size()){
b[idx++]=1;
}
else{
if(s[i+1]=='0'){
b[idx++]=10;
i++;
}
else{
b[idx++]=1;
}
}
}
else
b[idx++]=mp[s[i]];
}
sort(b,b+5);
for(int i=0;i<5;i++){
a[cnt].element[i]=b[i];
}
//龙顺子
if(b[0]==1&&b[1]==10&&
b[2]==11&&b[3]==12&&b[4]==13)
return 8;
int x=b[0];
bool flag=true;
map<int,int> p;
for(int i=0;i<5;i++){
p[b[i]]++;
if(i>0){
if(b[i]!=++x)
flag=false;
}
}
//顺子
if(flag)
return 7;
for(int j=0;j<10;j++){
a[cnt].c[j]=a[cnt].d[j]=0;
}
for(int j=10;j<15;j++){
a[cnt].d[j]=0;
}
for(map<int,int>::iterator t=p.begin();t!=p.end();t++){
a[cnt].c[t->second]=t->first;
a[cnt].d[t->first]=t->second;
}
int size=p.size();
map<int,int>::iterator it=p.begin();
//4张牌相等
if(size==1)
return 6;
else if(size==2){
//4张牌相等
if(it->second==4||it->second==1)
return 6;
//3张牌相等,另外2张也相等
return 5;
}
else if(size==3){
while(it!=p.end()){
//3张牌相等
if(it->second==3)
return 4;
it++;
}
//有2个不同的对子
return 3;
}
else if(size==4){
//2张牌相等
return 2;
}
else
//大牌
return 1;
}
int main()
{
mp['A']=1;mp['2']=2;mp['3']=3;mp['4']=4;mp['5']=5;
mp['6']=6;mp['7']=7;mp['8']=8;mp['9']=9;
mp['J']=11;mp['Q']=12;mp['K']=13;
while(~scanf("%d",&n)){
for(int cnt=0;cnt<n;cnt++){
scanf("%s",s1);
scanf("%s",s2);
string element=s2;
a[cnt].val=Value(s2,cnt);
a[cnt].name=s1;
}
sort(a,a+n);
for(int i=0;i<n;i++){
printf("%s\n",a[i].name.c_str());
}
}
return 0;
}
记一次教训!!!!!
在重载
<
<
< 时,
有一个地方忘记写 return ,但在本地编译时被优化了,提交OJ一直提示段错误,一开始以为是 map 的 [] 没有对边界的判断,或者其他数组越界问题,也没有想到没写 return 这个问题(主要是重载那里写得有点乱),把所有数组和map在每组数据结束后都清空了一遍,还把 map 都改成数组了,每种情况也都出了几组数据,结果都正确,提交后还是段错误,心态有点崩,后来单步进 sort 函数调试,才发现这个低级问题…