[week9]东东学打牌
文章目录
- 题意
- Input
- Output
- 输入样例
- 输出样例
- 提示
- 分析
- 总结
- 代码
题意
最近,东东沉迷于打牌。所以他找到 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。请你告诉东东,全场人的排名
Input
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。
Output
对于每组测试数据,输出 n 行,即这次全场人的排名。
输入样例
3
DongDong AAA109
ZJM 678910
Hrz 678910
输出样例
Hrz
ZJM
DongDong
提示
分析
重点是读小作文题目,以及根据题目给出约束条件建立解题构架。
- 题目分析
根据题目可以得到:
- 牌面大小规定
- 牌数
- 牌型规定
- 牌型比较方法
- 玩家排序方法
总结题目需要实现的目标,就是分析所有玩家手牌,根据手牌输出玩家排序。
到这里,读完题并完全理解后,我们知道我们需要做的事情是:
- 获得玩家名称
- 获得玩家手牌
- 整理手牌
- 比较手牌
- 根据比较结果给玩家排序
- 输出玩家排序
- 代码实现和分析
那么接下来就根据需要完成的目标来逐步建立解题结构:
1. 玩家类型
根据目标可以发现,我们需要获取一个玩家的名称、手牌。因此在自定义的玩家结构体中首先自然是要包含这两个基本数据域。
但是,什么样的玩家结构才能让之后的比较和排序更加容易呢?
首先作为基本的比较条件,我们需要记录玩家的手牌牌型。其次,在每个相同牌型的比较中,还需要通过一些其他特殊牌面大小来完成,例如对子值、三个值、炸弹值、顺子最大值…
根据总结可以发现,除去两对需要比较三次之外,所有的相同牌型比较都最多需要两个值。因此根据这个特点,我们可以在结构体中加入三个数据域来记录这些特殊值,方便快速比较排序。(在代码中我是用的pair加一个int)
2. 整理手牌
当确认了所有玩家和他们的手牌后,第一步自然是整理手牌,确认它们的牌型以及特殊值,才能进行下一步的比较和排序。
1)字符转换为大小
因为输入的名称和手牌都是字符串类型。因此要确保手牌字符串中的每个字符都能转换为正确的int值。所以可以用map建立一个char到int的映射。
但是有个问题,数字10是两位数,拥有两个字符,该如何转换?我处理的方式很简单,因为每次遍历最先扫描到的一定是“1”,而所有出现的面值中除了“10”外所有面值没出现“1”。因此可以用“1”唯一标识“10”,建立“1”到10的映射即可。
那么在遍历中,分为出现“10”和不出现两种情况,在前者中每当扫描到“0”时直接忽略即可。不出现的情况则代表着手牌字符串的长度一定为5,因为除去“10”所有面值都只有一个字符。
2)整理出现的面值及其个数
为了方便判断牌型,我们需要知道出现了多少面值,以及每个面值出现了多少次。
所以在转换过程中用一个vecor记录出现的所有面值,用一个int数组存储每个面值大小出现的次数即可。0即未出现。
首先判定是否出现龙顺,即判断是否出现5个面值且分别为10、J、Q、K、A。若判断成功,则记录牌型并直接返回。
在遍历前,先将出现的面值按升序排序,方便区分顺子和大牌。
若不是龙顺,再开始依次遍历所有出现的面值,根据当前面值出现的次数以及之前玩家记录的牌型来判断出当前的新牌型。如,若存在一个面值出现3次,且该玩家已经记录为对子,说明该玩家更新为了三带二类型。
如果面值数量为5,若任意两个相邻面值之间的差大于1,就说明该手牌一定不是顺子,而是大牌。因此,当遍历结束后,牌型仍然一次未更新时,就代表着这个牌型一定是顺子。
在遍历过程中,当玩家牌型达到其所及的最高牌型时,即代表其最终牌型已确定,可直接记录对应特殊值并返回。这个意思就是,当一个牌型为对子或三个时,其仍可能升级为两对、三带二,但是诸如炸弹、三带二一旦出现就一定是最终牌型,不会再改变。
由于我们其实不太关心这些面值具体是多少,只用知道其特征来判断牌型即可。所以在判断牌型的过程中,我们就可以将对子、三个、炸弹等信息直接存入到结构体中。除此之外,我们可以利用有序的面值序列来存储面值和或是剩余牌面值等特殊信息。比如,对子中剩余牌的面值大小就一定为出现的所有面值之和减去已记录的两个对子面值。
3. 比较牌型
首先可明确的是,牌型越大的玩家排名一定越高。而牌型相同的玩家再根据其所属牌型的对应比较方法进行降序排列。
所以我们可以用一个8列的不规则数组来记录对应属于每个牌型的所有玩家。则大体的输出顺序一定是从牌型8的玩家到1的玩家。
显然,最简单的办法就是遍历到某牌型时调用其对应的专属比较函数对当前该类型中所有玩家进行排序,最后依次输出即可。
而每个牌型根据其比较方式,再加上名字字典序的比较,编写对应的自定义比较函数即可,利用sort就能实现对这些玩家的快速排序了。
- 问题
其实这个题也并不难,虽然我的代码有点点长。但是在写完之后基本就知道自己一定会对。不过我前两次并没有ac!【本猪当时是震惊的】
返回去看,发现是一个很小的粗心点没有纠正,扼杀了我的第二次一次ac体验:
- 存储特殊面值
由于我的玩家结构体中采用的是pair来记录特殊面值,因此在不同牌型中,哪个类型的面值放在first,哪个放在second,容易出错并且混淆。尤其是之后又有大量的自定义函数,其中包含了大量引用比较和判断。在第一遍没有细心或是写完没有检查的话,容易出错。
我出错的地方就是对子这个牌型。由于我设置所有第一次出现的对子都放在第二位,方便出现三带二时为三个的面值让路。因此只有一个对子的情况中,也仍然是pair的第二位存放的对子,而剩余三个值的和在第一位。这一个小点就连续出错在了判断、记录和值、比较函数三个地方。导致我失去了一次ac的机会【555】
- 包含10
除此之外,在粗略的检查中我也发现了一个最开始设计有问题的地方:也就是若手牌含有10的遍历转换中,最开始我规定的是该情况下遍历长度为6,也就是只增加了一个0的位置,但是在我自己设计数据调试的时候就猛然醒悟,显然可能存在多个10,所以就改为了遍历字符串长度。于是我突然现在写着也醒悟了,我完全不用分开情况,只用遇到0就跳过就可以了
[week9]东东学打牌相关推荐
- 【Week9 作业】A - 咕咕东的目录管理器、B - 东东学打牌、C - 签到题,独立思考哈
A - 咕咕东的目录管理器 题意: 咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响,时不时发生故障,他受不了了,想要写一个高效易用零bug的操作系统 -- 这工程量太大了,所以他定了一个小目标, ...
- 程序设计Week9——B-东东学打牌
B-东东学打牌 题目描述 Input Output 解题思路 实现代码 总结 题目描述 打牌,只考虑牌的数值,不考虑花色,每个人五张手牌,每种牌数量无限,手牌大小比较规则: 序号越大,牌越大,在得知全 ...
- WEEK9 作业 B - 东东学打牌
B - 东东学打牌 题目描述 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由 ...
- B - 东东学打牌(Week9.2作业)
题面 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由一个值表示.A, 2, ...
- Week9 作业——B - 东东学打牌
题目 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由一个值表示.A, 2, ...
- week9 B-东东学打牌
题面 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由一个值表示.A, 2, ...
- week9 - B - 东东学打牌
题意: 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由一个值表示.A, 2, ...
- 【Week9作业 B】东东学打牌【模拟】
题意: 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由一个值表示.A, 2, ...
- 东东学打牌 Week9作业B题
题目: 最近,东东沉迷于打牌.所以他找到 HRZ.ZJM 等人和他一起打牌.由于人数众多,东东稍微修改了亿下游戏规则: 所有扑克牌只按数字来算大小,忽略花色. 每张扑克牌的大小由一个值表示.A, 2, ...
最新文章
- wordpress中文乱码处理方法
- 成功解决SyntaxError: import * only allowed at module level
- Linux 学习笔记_10_Shell编程_2_Shell编程语法(三)
- 公众号推荐:Python入门、统计学、推荐系统、机器学习、深度学习、数据分析...
- VC中海量文件读写类设计与应用(转)
- IP通信基础 实验三
- 【R】ployroot函数求解多项式方程
- 箭头函数和普通函数有什么区别?
- SAP License:PS中比较常用的事务代码
- 数据分析——十大数据分析模型
- 浅学DSP原理及应用
- 树莓派搭建全功能NAS服务器(07):管理你的书库随心阅读
- 华硕电脑开机 C键和空格建不灵了怎么办
- web开发第三方登陆之微信登陆
- 电源纹波怎么测量,纹波和噪声的区别
- Tether聘请前银行分析师首席合规官
- python爬取网易云音乐生成王力宏歌曲词云
- NET Namespace(1)
- SUSE Linux Enterprise Server for SAP Applications15 SP3 下载及安装教程
- 基本数据类型 int操作 bool布尔操作 str字符串操作 for in 循环