于2020/02/24记录。

德州扑克属实是个带难题。本题解简单易懂,命名合理,应该比较好理解。

题目如下:

最近,阿夸迷于德州扑克。所以她找到了很多人和她一起玩。由于人数众多,阿夸必须更改游戏规则:

所有扑克牌均只看数字,不计花色。

每张卡的值为1、2、3、4、5、6、7、8、9、10、11、12、13 中的一种(对应A,2、3、4、5、6、7, 8、9、10,J,Q,K)

每位玩家从一副完整的扑克牌(没有大小王)中抽出五张扑克牌,可能出现的手牌的值从低到高排列如下:

高牌:不包含以下牌的牌。对于都是高牌的牌,按照五张牌的值的和进行从大到小排序。

对子:手中的5张牌中有2张相同值的牌。对于都拥有对子的牌,按构成该对子的牌的值进行从大到小地排序。如果这些都相同,则按手牌中余下3张牌的值的和进行从大到小排序。

两对:手中拥有两对不同的对子。对于都包含两对的手牌,按其最高对子的值进行从大到小排序。如果最高对子相同,则按另一个对子的值从大到小地进行排序。如果这些值相同,则按剩余牌的值从大到小地进行排序。

三条:手中拥有3张相同值的牌。对于都包含三条的手牌按构成三条的牌的值进行从大到小地排序。如果这些值相同,则按剩余牌的值从大到小地进行排序。

满堂红:手中拥有一个三条和一个对子。同理,先按三条大小排序,如果三条大小相同,则按对子大小进行排序。

四条:手中拥有4张相同值的牌。对于都包含四条的手牌按构成四条的牌的值进行从大到小地排序。如果这些值相同,则按剩余牌的值从大到小地进行排序。

顺子:手中拥有5张连续值的卡。对于都包含顺子的手牌按顺子最大的牌进行排序。

皇家同花顺:手中拥有10到A(10、J、Q、K、A)。是最大的手牌!

现在,阿夸已经知道了每个人的手牌,她想要知道所有人的排名列表。如果玩家的手牌大小相等,则按玩家名字的字典序输出。保证没有重复的名字。你能帮帮她吗?

输入格式:

第一行包含一个正整数 N (1<=N<=100000) ,表示玩家的人数。

接下来 N 行,每行包含两个字符串:m (1<=|m|<=10 ) ,表示玩家的名字;s (1<=|s|<=10),表示玩家的手牌。

输出格式:

输出 N个玩家的排名列表。

输入样例:

3

Alice AAA109

Bob 678910

Boa 678910

输出样例:

Boa

Bob

Alice

解:

头文件

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

本题包含一个结构体struct People、三个函数:①int trans(string str)②void deal_the_level_of(People x,int cur)③int cmp(People a,People b)、主函数:

struct People
{
string name;
string s;
int card[14];
double level;//大等级从1-8 细分等级顺序用小数点来算大小
}f[100005];

结构体的成员很简单:名字和手牌都为string类,方便输入输出和拆分;card数组分别储存这个人拥有的牌的情况;最后一个最重要的等级,我用了double型来定义,通过小数点来判定牌面大小的优先级;同时定义一个全局变量的数组方便后续输入和处理。

int trans(string str)
{
if(str=="A")return 1;
if(str=="2")return 2;
if(str=="3")return 3;
if(str=="4")return 4;
if(str=="5")return 5;
if(str=="6")return 6;
if(str=="7")return 7;
if(str=="8")return 8;
if(str=="9")return 9;
if(str=="10")return 10;
if(str=="J")return 11;
if(str=="Q")return 12;
if(str=="K")return 13;
}

trans函数的功能想必大家都不陌生,之前的白话文编程作业多次需要将字符串转化为有数值的数字,这个函数也是一个将string类的字符串转化为数字,即对应的牌面。

int cmp(People a,People b)
{
if(a.level!=b.level)return a.level>b.level;
else return a.name<b.name;
}

这个cmp(compare)函数是给后面要用的sort函数作为其第三个参数,说白了就是告诉sort怎么进行排序。本题是按照牌面从大到小来排,如果牌面相同就按照名字的字典序来排。由于本题用的是string类,进行字典序排序十分简单,一个小于号“<”就搞定。

下面是本题最重要的函数!!由于这个函数很长,有70多行,所以将解释放入注释中。

函数顾名思义--deal the level of (某个People型的变量):处理People型变量x的等级。

void deal_the_level_of(People x,int cur)    //current 当前的那个下标
{
int single_value=0;//剩下单张牌总值的和
int couple1=0,couple2=0;//有一个对子 、有两个对子 其值为对子对应的牌面
int three=0; //判断是否有三条
int four=0; //判断是否有四条
bool line=false;//判断是否有顺子 有的话更为true
int maxn;//顺子中最大的牌 for(int i=1;i<=13;i++)
{
if(x.card[i]==1)//遇到这张牌是单张的
{
int judge=1,j;//判断顺子
for(j=i+1;j<=i+4;j++)judge*=x.card[j];//不断相乘,只有全都是 1 ,乘出来才会为1.
if(judge==1){//是顺子
line=true;
maxn=j-1;
break;
}
else single_value+=i;
}
if(x.card[i]==2)//如果这张牌拥有两张
{
if(couple1==0)couple1=i;//如果之前没出现过对子
else couple2=i;//之前出现过对子了,那这个就是第二个对子
}
if(x.card[i]==3)three=i;//如果这张牌拥有三张
if(x.card[i]>=4)//这张牌拥有四张或五张,一样的都归为 四条 这个级别。
{
four=i;
if(x.card[i]==5)single_value+=i;//五张一样的 剩下那张归为单张
}
}
/*
注意!如果一个大等级中,有多个排序的优先级
那么:
第一优先级 乘 0.01
第二优先级 0.0001
第三优先级 0.000001
因为最大的单张牌面“K”的值为13,超过10了,如果少乘一个0会影响到大等级。
*/
if(x.card[10]*x.card[11]*x.card[12]*x.card[13]*x.card[1]==1)x.level+=8.0;//皇家同花顺 ,永远滴神!
else if(line)//顺子 第7级
{
x.level=7.0;
x.level+=maxn*0.01;
}
else if(four)//四条 第6级
{
x.level=6.0;
x.level+=four*0.01+single_value*0.0001;
}
else if(three)//满堂红或三条
{
if(couple1){//有一个对子,满堂红 第5级
x.level=5.0;
x.level+=three*0.01+couple1*0.0001;
}
else{//三条 第4级
x.level=4.0;
x.level+=three*0.01+single_value*0.0001;
}
}
else if(couple1)//两对或对子
{
if(couple2){//两对 第3级
x.level=3.0;
x.level+=couple2*0.01+couple1*0.0001+single_value*0.000001;
}
else{//单个对子 第2级
x.level=2.0;
x.level+=couple1*0.01+single_value*0.0001;
}
}
else {//高牌 最弱的第1级
x.level=1.0;
x.level+=single_value*0.0001;
}
f[cur]=x;//不用指针,将其转移给当前的这个f (因为f数组是全局变量) ,不然f数组的值不会改变的
}

主函数:

解释还是放在注释里啦!

int main()
{
int n,value;
string tmp;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>f[i].name>>f[i].s;
string str=f[i].s;
for(int j=0,t=0;t<5;t++)//共五张牌
{
if(str[j]!='1'){ //不为10
tmp=str[j]; //提取出这个字符
value=trans(tmp);//转换这个字符为对应的值
f[i].card[value]++;//该值的手牌数+1
j++;
}
else{ //遇到10了,只有 10 才会出现 1这个数字,因为牌值为1的是 A
f[i].card[10]++;
j+=2; //跳两格
}
}
deal_the_level_of(f[i],i);//处理f[i],记得带下标i
}
sort(f,f+n,cmp); //排序
for(int i=0;i<n;i++)cout<<f[i].name<<endl; //输出
return 0;
}

我遇到的问题:

细节实在太多了,大量的分类情况堆在一起会十分混乱,所以在编写时最好用笔在一张草稿纸写出分类、优先级排序的思路。

一共有10个测试点,我的过程为:

通过0个点->通过第1、2个点:修正了“两对”这个情况的bug。

错误代码为

		if(x.card[i]==2)//如果这张牌拥有两张
{
if(couple1==0)couple1=i;//如果之前没出现过对子
if(couple1)couple2=i;//之前出现过对子了,那这个就是第二个对子
}

写了两个if语句,问题在于两条语句的顺序错了。执行完第一句后,couple1已经被赋值了,第二句他必不可能为0,所以第二句也会被执行,从而couple2会变成和couple1一样的值。

正确代码应为

		if(x.card[i]==2)//如果这张牌拥有两张
{
if(couple1==0)couple1=i;//如果之前没出现过对子
else couple2=i;//之前出现过对子了,那这个就是第二个对子
}

或者将两句顺序调换。

通过2个点->AC:修正了满堂红和三条的bug,我原先没判断三子的大小直接判断了后面剩余牌的大小,此块优先级应该为:先比较三子大小、后比较剩余两张牌的大小。

错误代码为

	else if(three)//满堂红或三条
{
if(couple1){//有一个对子,满堂红 第5级
x.level=5.0;
x.level+=couple1*0.01;
}
else{//三条 第4级
x.level=4.0;
x.level+=single_value*0.01;
}
}

正确代码应为

	else if(three)//满堂红或三条
{
if(couple1){//有一个对子,满堂红 第5级
x.level=5.0;
x.level+=three*0.01+couple1*0.0001;
}
else{//三条 第4级
x.level=4.0;
x.level+=three*0.01+single_value*0.0001;
}
}

希望能对大家有所帮助:)

完整代码:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct People
{
string name;
string s;
int card[14];
double level;//大等级从1-8 细分等级顺序用小数点来算大小
}f[100005];
int trans(string str)
{
if(str=="A")return 1;
if(str=="2")return 2;
if(str=="3")return 3;
if(str=="4")return 4;
if(str=="5")return 5;
if(str=="6")return 6;
if(str=="7")return 7;
if(str=="8")return 8;
if(str=="9")return 9;
if(str=="10")return 10;
if(str=="J")return 11;
if(str=="Q")return 12;
if(str=="K")return 13;
}
int cmp(People a,People b)
{
if(a.level!=b.level)return a.level>b.level;
else return a.name<b.name;
}
void deal_the_level_of(People x,int cur)//current 当前的那个下标
{
int single_value=0;//剩下单张牌总值的和
int couple1=0,couple2=0;//有一个对子 、有两个对子 其值为对子对应的牌面
int three=0; //判断是否有三条
int four=0; //判断是否有四条
bool line=false;//判断是否有顺子 有的话更为true
int maxn;//顺子中最大的牌 for(int i=1;i<=13;i++)
{
if(x.card[i]==1)//遇到这张牌是单张的
{
int judge=1,j;//判断顺子
for(j=i+1;j<=i+4;j++)judge*=x.card[j];//不断相乘,只有全都是 1 ,乘出来才会为1.
if(judge==1){//是顺子
line=true;
maxn=j-1;
break;
}
else single_value+=i;
}
if(x.card[i]==2)//如果这张牌拥有两张
{
if(couple1==0)couple1=i;//如果之前没出现过对子
else couple2=i;//之前出现过对子了,那这个就是第二个对子
}
if(x.card[i]==3)three=i;//如果这张牌拥有三张
if(x.card[i]>=4)//这张牌拥有四张或五张,一样的都归为 四条 这个级别。
{
four=i;
if(x.card[i]==5)single_value+=i;//五张一样的 剩下那张归为单张
}
}
/*
注意!如果一个大等级中,有多个排序的优先级
那么:
第一优先级 乘 0.01
第二优先级 0.0001
第三优先级 0.000001
因为最大的单张牌面“K”的值为13,超过10了,如果少乘一个0会影响到大等级。
*/
if(x.card[10]*x.card[11]*x.card[12]*x.card[13]*x.card[1]==1)x.level+=8.0;//皇家同花顺 ,永远滴神!
else if(line)//顺子 第7级
{
x.level=7.0;
x.level+=maxn*0.01;
}
else if(four)//四条 第6级
{
x.level=6.0;
x.level+=four*0.01+single_value*0.0001;
}
else if(three)//满堂红或三条
{
if(couple1){//有一个对子,满堂红 第5级
x.level=5.0;
x.level+=three*0.01+couple1*0.0001;
}
else{//三条 第4级
x.level=4.0;
x.level+=three*0.01+single_value*0.0001;
}
}
else if(couple1)//两对或对子
{
if(couple2){//两对 第3级
x.level=3.0;
x.level+=couple2*0.01+couple1*0.0001+single_value*0.000001;
}
else{//单个对子 第2级
x.level=2.0;
x.level+=couple1*0.01+single_value*0.0001;
}
}
else {//高牌 最弱的第1级
x.level=1.0;
x.level+=single_value*0.0001;
}
f[cur]=x;//不用指针,将其转移给当前的这个f (因为f数组是全局变量) ,不然f数组的值不会改变的
} int main()
{
int n,value;
string tmp;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>f[i].name>>f[i].s;
string str=f[i].s;
for(int j=0,t=0;t<5;t++)//共五张牌
{
if(str[j]!='1'){ //不为10
tmp=str[j]; //提取出这个字符
value=trans(tmp);//转换这个字符为对应的值
f[i].card[value]++;//该值的手牌数+1
j++;
}
else{ //遇到10了,只有 10 才会出现 1这个数字,因为牌值为1的是 A
f[i].card[10]++;
j+=2; //跳两格
}
}
deal_the_level_of(f[i],i);//处理f[i],记得带下标i
}
sort(f,f+n,cmp); //排序
for(int i=0;i<n;i++)cout<<f[i].name<<endl; //输出
return 0;
}

好难TOT

PTA-德州扑克 题解的更多相关文章

  1. 第一周PTA笔记 德州扑克题解

    德州扑克 最近,阿夸迷于德州扑克.所以她找到了很多人和她一起玩.由于人数众多,阿夸必须更改游戏规则: 所有扑克牌均只看数字,不计花色. 每张卡的值为1.2.3.4.5.6.7.8.9.10.11.12 ...

  2. java和h5 canvas德州扑克开发中(二)

    德州扑克网页源码在github上分享 https://github.com/lxr1907/pokers 感兴趣的可以上去看下. 1.通讯使用websocket,主要在message.js中. 2.用 ...

  3. java和h5 canvas德州扑克开发中(一)

    先附上我的德州扑克测试地址 http://120.26.217.116:8080/LxrTexas/texasIndex.html 我和一个朋友的德州扑克历时一个多月开发,目前已经基本可玩. 前端主要 ...

  4. 德州扑克AI WEB版

    继续之前的德州扑克话题,上次的DOS界面确实没法看,我女朋友说这是什么鬼.哈哈,估计只有自己能玩了 这两天重构了一下界面,基于web服务器和浏览器来交互. 服务器和客户端之间用websocket通信, ...

  5. 德州扑克AI实现 TexasHoldem Poker

    参考了一下这篇文献,http://cowboyprogramming.com/2007/01/04/programming-poker-ai/ 自己用go实现了一个德州扑克AI,效果还可以. 正常和它 ...

  6. [swustoj 1088] 德州扑克

    德州扑克(1088) 问题描述 德州扑克是一款风靡全球的扑克游戏.德州扑克一共有52张牌,没有王牌.每个玩家分两张牌作为“底牌”,五张由荷官陆续朝上发出的作为公共牌.开始的时候,每个玩家会有两张面朝下 ...

  7. 2015华为德州扑克入境摘要——软体project

    直到6一个月2号下午12时00,华为长达一个月的德州扑克锦标赛落下帷幕也被认为是. 我们的团队一直共同拥有3民,间.一个同学(吴)负责算法设计,一个同学(宋)负责分析消息,而我负责的实现框架设计和详细 ...

  8. 德州扑克AI--Programming Poker AI(译)

    前言: 最近在研究德州扑克的AI, 也想由浅入深的看下, 在网上找了一圈, 发现很多文章都提到了一篇文章: Programming Poker AI. 仔细拜读了一下, 觉得非常不错. 这里作下简单的 ...

  9. 德州扑克AI

    德州扑克: 1:outs数,就是所听的牌的数量. 例子: 1:听顺子 4567 outs数就是8,能够成顺子的牌为3和8. 5689 outs数就是4,能够成顺子的牌只有7. 2:听同花     35 ...

随机推荐

  1. linux 使用nfs 服务实现远程共享

    首先安装 apt install -y nfs-kernel-server nfs-common 编辑配置文件 vim /etc/exports 添加内容: /root/test *(rw,sync, ...

  2. Android Studio 找不到夜神模拟器的解决办法

    Android Studio 找不到夜神模拟器的解决办法 1.启动夜神模拟器 2.找到你电脑上的夜神安装目录,在bin目录下打开cmd窗口,运行命令 nox_adb.exe connect 127.0 ...

  3. Vscode开发Java环境搭建

    VSCode 开发 JAVA 微软为 Java 开发者推出了一个 Visual Studio Code 的安装程序.Visual Studio Code 中目前提供了许多 Java 扩展. 该软件包可 ...

  4. Flink1.9重大改进和新功能

    一.Flink1.9.0的里程碑意义 二.重构 Flink WebUI Flink社区讨论了现代化 Flink WebUI 的提案,决定采用 Angular 的最新稳定版来重构这个组件.从Angula ...

  5. Centos7 使用Docker 部署mssql 2017

    mssql是.NET的标配,一般使用.NET的人基本都用mssql. 以前mssql只能支持windows平台,从微软打出 拥抱开源 的口号开始,mssql的2017 版本,开始支持linux系统. ...

  6. Android布局管理器-从实例入手学习相对布局管理器的使用

    场景 AndroidStudio跑起来第一个App时新手遇到的那些坑: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103797 ...

  7. python——异常(1),捕获特定异常

    """1.捕获指定异常,异常类型有多种2.若尝试执行的代码异常类型与捕获的异常类型不同则报错3.try下方一般只放一行代码,若有多行可能异常代码,则捕获一个异常类型后函数 ...

  8. TCP/IP详解阅读记录----第一章 概述

    1.TCP/IP协议族中不同层次的协议 2.五类互联网地址 3.各类IP地址范围 4.数据进入协议栈时的封装过程 5.以太网数据帧的分用过程

  9. 【macOS使用技巧】使用空格键快速预览文件内容

    Quickview 是mac系统上一个强大的预览功能, 可以预览 mp4 mov等音频文件, 当然图片.文本.也都可以进行预览. 在系统中如果你希望快速浏览一下文件而不想打开的文件的话只要选择文件然后 ...

  10. 从表单驱动到模型驱动,解读低代码开发平台的发展趋势 ZT

    原文地址:https://www.grapecity.com.cn/blogs/read-the-trends-of-low-code-development-platforms 随着社会数字化进程的 ...