SDU_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

题目分析

本题是打牌模拟,依然是老套路:定义结构体+map映射点数+定牌型+sort+cmp比较函数

首先建立输入与可比较数据类型(即int)的映射,然后读入每个人的信息(名字+手牌),然后对手牌进行排序,并进行定牌型操作。通过之前定义好的cmp函数对这n个人进行排序,再输出结果。

要记得每次输出后清空结构体,手动适配即可,struct用memset会出现可怕的结果

注意

不能用while ((temp=getchar())!='\n')判断一行的结束,因为最后一条数据没有回车,会RE。慎用getchar()和getline(),除非不得不用。

代码

#define _ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#include <bits/stdc++.h>
//#include <iostream>
//#include<algorithm>

using namespace std;

map<char,int> poker;
struct node
{//每个人
    string name;
    vector<int> mypoker;
    int label;//牌型
    int boom[2];//炸弹大小和剩余牌
    int threePtwo[2];//3+2
    int three[2];//3+(1+1)
    int twoPtwo[3];//2+2+1
    int two[2];//2+(1+1+1)
    int one;//5*1
}stu[100009];

bool cmp(node a,node b)
{
    if(a.label!=b.label)return a.label>b.label;
    else if(a.label==8)return a.name<b.name;
    else if(a.label==7)
    {
        if(a.mypoker[4]!=b.mypoker[4])return a.mypoker[4]>b.mypoker[4];
        else return a.name<b.name;
    }
    else if(a.label==6)
    {
        if(a.boom[0]!=b.boom[0])return a.boom[0]>b.boom[0];
        else if(a.boom[1]!=b.boom[1])return a.boom[1]>b.boom[1];
        else return a.name<b.name;
    }
    else if(a.label==5)
    {
        if(a.threePtwo[0]!=b.threePtwo[0])return a.threePtwo[0]>b.threePtwo[0];
        else if(a.threePtwo[1]!=b.threePtwo[1])return a.threePtwo[1]>b.threePtwo[1];
        else return a.name<b.name;
    }
    else if(a.label==4)
    {
        if(a.three[0]!=b.three[0])return a.three[0]>b.three[0];
        else if(a.three[1]!=b.three[1])return a.three[1]>b.three[1];
        else return a.name<b.name; 
    }
    else if(a.label==3)
    {
        if(a.twoPtwo[0]!=b.twoPtwo[0])return a.twoPtwo[0]>b.twoPtwo[0];
        else if(a.twoPtwo[1]!=b.twoPtwo[1])return a.twoPtwo[1]>b.twoPtwo[1];
        else if(a.twoPtwo[2]!=b.twoPtwo[2])return a.twoPtwo[2]>b.twoPtwo[2];
        else return a.name<b.name; 
    }
    else if(a.label==2)
    {
        if(a.two[0]!=b.two[0])return a.two[0]>b.two[0];
        else if(a.two[1]!=b.two[1])return a.two[1]>b.two[1];
        else return a.name<b.name; 
    }
    else if(a.label==1)
    {
        if(a.one!=b.one)return a.one>b.one;
        else return a.name<b.name; 
    }
}

int main()
{
    // _;
    // freopen("in.txt","r",stdin); 
    poker['A']=1;
    poker['2']=2;
    poker['3']=3;
    poker['4']=4;
    poker['5']=5;
    poker['6']=6;
    poker['7']=7;
    poker['8']=8;
    poker['9']=9;
    poker['1']=10;//注意
    poker['J']=11;
    poker['Q']=12;
    poker['K']=13;

    int n;//组数
    while (cin>>n)
    {
        // getchar();//这里注意!!!cin后的回车留在缓冲区
        //整理手牌
        for (int i = 0; i < n; i++)
        {
            // char temp;
            int temp_num;
            string str_temp;
            // while ((temp=getchar())!=' ')
            // {
            //     stu[i].name.push_back(temp);
            // }
            //最后一组数据的时候没有回车!不能通过这个终止条件判断结束!
            // while ((temp=getchar())!='\n')
            // {
            //     if(temp=='1')getchar();//吞10的0
            //     temp_num=poker[temp];
            //     stu[i].mypoker.push_back(temp_num);
            // }
            cin>>stu[i].name;
            cin>>str_temp;
            for (int j = 0; j < str_temp.length(); j++)
            {
                stu[i].mypoker.push_back(poker[str_temp[j]]);
                if(str_temp[j]=='1')j++;//处理10的0, 长长记性:这里是'1'而非1!!!
            }
            // getchar();//吞掉最后的回车键,但是也不对!因为不知道有没有下一组数据,会死循环
            
            sort(stu[i].mypoker.begin(),stu[i].mypoker.end());

            if(stu[i].mypoker[0]==1 &&stu[i].mypoker[1]==10 &&stu[i].mypoker[2]==11&&stu[i].mypoker[3]==12&&stu[i].mypoker[4]==13)
            {
                 stu[i].label=8;
                 continue;        
            }
            if(stu[i].mypoker[4]==stu[i].mypoker[3]+1&&stu[i].mypoker[3]==stu[i].mypoker[2]+1&&stu[i].mypoker[2]==stu[i].mypoker[1]+1&&stu[i].mypoker[1]==stu[i].mypoker[0]+1)
            {
                stu[i].label=7;
                continue;
            }
            int box[14];//牌数箱子
            int mx_temp=0;
            memset(box,0,sizeof(box));
            for(int num=0;num<5;num++)
            {
                box[stu[i].mypoker[num]]++;
                mx_temp=max(box[stu[i].mypoker[num]],mx_temp);
            }
            if(mx_temp==4)
            {
                for(int j=1;j<=13;j++)
                {
                    if(box[j]==4)stu[i].boom[0]=j;
                    if(box[j]==1)stu[i].boom[1]=j;
                }
                stu[i].label=6;
                continue;    
            }
            if(mx_temp==3)
            {//i和j不要混!!!wa的时候检查一些变量是否互相干扰!!!
                for(int j=1;j<=13;j++)
                {
                    if(box[j]==3){stu[i].threePtwo[0]=j;stu[i].three[0]=j;}
                    if(box[j]==2)stu[i].threePtwo[1]=j;
                    if(box[j]==1)stu[i].three[1]+=j;
                }
                if(stu[i].threePtwo[1]!=0)stu[i].label=5;
                else stu[i].label=4;
                continue;
            }
            int two1=0,two2=0;
            for(int j=1;j<=13;j++)
                {
                    if(box[j]==2)
                    {
                        if(two1!=0)two2=j;
                        else two1=j;
                    }
                }
            if(two1!=0&&two2!=0)
            {
                if(two1<two2)swap(two1,two2);
                for(int j=1;j<=13;j++)if(box[j]==1)stu[i].twoPtwo[2]=j;
                stu[i].twoPtwo[0]=two1;
                stu[i].twoPtwo[1]=two2;
                stu[i].label=3;
                continue;
            }
            if(two1!=0&&two2==0)
            {
                for(int j=1;j<=13;j++)
                    if(box[j]==1)stu[i].two[1]+=j;
				stu[i].two[0]=two1;
                stu[i].label=2;
                continue;
            }
            for(int num=0;num<5;num++)stu[i].one+=stu[i].mypoker[num];
            stu[i].label=1;
        }

        //排序并输出
        sort(stu,stu+n,cmp);
        for(int i=0;i<n;i++)
            cout<<stu[i].name<<endl;
        
        //清空以备后续使用
        for(int i = 0; i < n; i++)
        {
            stu[i].name= "";
            // stu[i].name.clear();
            while (!stu[i].mypoker.empty())
            {
                stu[i].mypoker.pop_back();
            }
            stu[i].label=0;
            stu[i].boom[0]=0;stu[i].boom[1]=0;
            stu[i].threePtwo[0]=0;stu[i].threePtwo[1]=0;
            stu[i].three[0]=0;stu[i].three[1]=0;
            stu[i].twoPtwo[0]=0;stu[i].twoPtwo[1]=0;stu[i].twoPtwo[2]=0;
            stu[i].two[0]=0;stu[i].two[1]=0;
            stu[i].one=0;
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值