第一周PTA笔记 德州扑克题解
德州扑克
最近,阿夸迷于德州扑克。所以她找到了很多人和她一起玩。由于人数众多,阿夸必须更改游戏规则:
所有扑克牌均只看数字,不计花色。
每张卡的值为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
思路:
一开始我是将牌型通过等级,数值,名字字典序来进行逐级排序,但这样会使代码冗长而繁琐,不易检查还会导致代码运行时间超出。而后通过查阅资料和询问转换了一下思路,就是将牌型分别转化为数字,再通过qsort函数对于数字大小进行比较。
牌型转换
for(i=0;i<N;i++)
{
n=strlen(p[i].s);
for(j=0;j<n;j++)
{
if(p[i].s[j]=='1'){//遇到1时肯定是数值为10的牌
for(r=j+1;r<n-1;r++)
{
p[i].s[r]=p[i].s[r+1];//将之后的牌都往前进一位
}
p[i].s[n-1]='\0';
p[i].s[j]=10;
}
else if(p[i].s[j]=='J')p[i].s[j]=11;
else if(p[i].s[j]=='Q')p[i].s[j]=12;
else if(p[i].s[j]=='K')p[i].s[j]=13;
else if(p[i].s[j]=='A')p[i].s[j]=1;
else if(p[i].s[j]=='2')p[i].s[j]=2;
else if(p[i].s[j]=='3')p[i].s[j]=3;
else if(p[i].s[j]=='4')p[i].s[j]=4;
else if(p[i].s[j]=='5')p[i].s[j]=5;
else if(p[i].s[j]=='6')p[i].s[j]=6;
else if(p[i].s[j]=='7')p[i].s[j]=7;
else if(p[i].s[j]=='8')p[i].s[j]=8;
else if(p[i].s[j]=='9')p[i].s[j]=9;}
一开始是直接将2看作字符‘2’,它的ASCII码值为50,再将其它数字以大小范围使之分布在50左右的地方,例如牌A就使它为49,但这样数值太大,到后面会不方便自己检查错误,于是直接将牌值转换为1、2、3等等。为了方便牌型判断,我对五张牌进行了非降序的排序:
for(j=0;j<4;j++)
{
for(r=0;r<4-j;r++)
{
if(p[i].s[r]<p[i].s[r+1]){
t=p[i].s[r];
p[i].s[r]=p[i].s[r+1];
p[i].s[r+1]=t;
}//对牌进行非降序排序 (冒泡排序法)
}
}
牌型判断
if(p[i].s[0]==p[i].s[4]){
p[i].b-=p[i].s[2]*4;//除去四条的牌数
p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001; //将判断标准分级乘以小数方便比较,我将每个小等级以0.01的数量级来分开,以0.1来分应该也是可以的
continue;
}//这是五张牌都相等的情况,判断为四条
else if(p[i].s[0]==p[i].s[3]||p[i].s[1]==p[i].s[4]){
p[i].b-=p[i].s[2]*4;
p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
} //判断四条
else if(p[i].s[1]==p[i].s[3]){
p[i].b-=p[i].s[2]*3;
p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
}//三条
else if(p[i].s[0]==p[i].s[2]){
if(p[i].s[3]==p[i].s[4]){
p[i].a=50+p[i].s[0]*0.01+p[i].s[3]*0.0001;
continue;
}//满堂红
else{
p[i].b-=p[i].s[0]*3;
p[i].a=40+p[i].s[0]*0.01+p[i].b*0.0001;
continue;
}//三条
}
else if(p[i].s[2]==p[i].s[4]){
if(p[i].s[0]==p[i].s[1]){
p[i].a=50+p[i].s[2]*0.01+p[i].s[0]*0.0001;
continue;
}//满堂红
else{
p[i].b-=p[i].s[2]*3;
p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
}//三条
}
else if(p[i].s[0]==p[i].s[1]){
if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
p[i].b=p[i].b-p[i].s[0]*2-p[i].s[3]*2;
p[i].a=30+p[i].s[0]*0.01+p[i].s[3]*0.0001+p[i].b*0.000001;
continue;
}//两对
else{
p[i].b-=p[i].s[0]*2;
p[i].a=20+p[i].s[0]*0.01+p[i].b*0.0001;
continue;
}//一对
}
else if(p[i].s[1]==p[i].s[2]){
if(p[i].s[3]==p[i].s[4]){
p[i].a=30+p[i].s[1]*0.01+p[i].s[3]*0.0001+p[i].s[0]*0.000001;
continue;
}//两对
else{
p[i].b-=p[i].s[1]*2;
p[i].a=20+p[i].s[1]*0.01+p[i].b*0.0001;
continue;
}//一对
}
else if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
p[i].b-=p[i].s[3]*2;
p[i].a=20+p[i].s[3]*0.01+p[i].b*0.0001;
continue;
}//一对
for(j=0;j<4;j++)
{
if(p[i].s[j]-p[i].s[j+1]!=1)break;
}//判断顺子和同花顺
if(j==4){
p[i].a=70+p[i].s[0]*0.01;
continue;
}//顺子
else if(j==3&&p[i].s[4]==1&&p[i].s[0]==13){
p[i].a=80;
continue;
}//同花顺
p[i].a=10+p[i].b*0.1;//高牌
}
这次遇到的问题归根结底还是cmp的编写,这让我一直只过了两个点(郁闷)
//错误代码
int cmp(const void *p1,const void *p2)
{
struct pai *c=(struct pai*)p1;
struct pai *d=(struct pai*)p2;
if(c->a!=d->a)return c->a<d->a?1:-1;
else return c->name>c->name?1:-1;
//正确代码
int cmp(const void *p1,const void *p2)
{
struct pai *c=(struct pai*)p1;
struct pai *d=(struct pai*)p2;
if(c->a!=d->a)return c->a<d->a?1:-1;
else {
if(strcmp(c->name,d->name)>0)return 1;//用字符串函数来判断名字字典序
else return -1;
}
}
不知道错误代码的错误究竟在哪,但正确代码比较好理解又不容易出错吧,希望知道我为什么错的能帮助指出哦
以下附上完整代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct pai{
char name[10];
char s[10];
double a;
int b;
}p[100005];
int main()
{
int cmp(const void *p1,const void *p2);
int N,i,j,r,n,x;
char t;
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%s %s",p[i].name,p[i].s);
}
for(i=0;i<N;i++)
{
n=strlen(p[i].s);
for(j=0;j<n;j++)
{
if(p[i].s[j]=='1'){
for(r=j+1;r<n-1;r++)
{
p[i].s[r]=p[i].s[r+1];
}
p[i].s[n-1]='\0';
p[i].s[j]=10;
}
else if(p[i].s[j]=='J')p[i].s[j]=11;
else if(p[i].s[j]=='Q')p[i].s[j]=12;
else if(p[i].s[j]=='K')p[i].s[j]=13;
else if(p[i].s[j]=='A')p[i].s[j]=1;
else if(p[i].s[j]=='2')p[i].s[j]=2;
else if(p[i].s[j]=='3')p[i].s[j]=3;
else if(p[i].s[j]=='4')p[i].s[j]=4;
else if(p[i].s[j]=='5')p[i].s[j]=5;
else if(p[i].s[j]=='6')p[i].s[j]=6;
else if(p[i].s[j]=='7')p[i].s[j]=7;
else if(p[i].s[j]=='8')p[i].s[j]=8;
else if(p[i].s[j]=='9')p[i].s[j]=9;}
p[i].b=0;
for(j=0;j<5;j++){
x=p[i].s[j];
p[i].b+=x;
}
for(j=0;j<4;j++)
{
for(r=0;r<4-j;r++)
{
if(p[i].s[r]<p[i].s[r+1]){
t=p[i].s[r];
p[i].s[r]=p[i].s[r+1];
p[i].s[r+1]=t;
}//对牌进行非降序排序
}
}
if(p[i].s[0]==p[i].s[4]){
p[i].b-=p[i].s[2]*4;//不是四条的牌数
p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
}
else if(p[i].s[0]==p[i].s[3]||p[i].s[1]==p[i].s[4]){
p[i].b-=p[i].s[2]*4;//不是四条的牌数
p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
}
else if(p[i].s[1]==p[i].s[3]){
p[i].b-=p[i].s[2]*3;
p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
}//三条
else if(p[i].s[0]==p[i].s[2]){
if(p[i].s[3]==p[i].s[4]){
p[i].a=50+p[i].s[0]*0.01+p[i].s[3]*0.0001;
continue;
}
else{
p[i].b-=p[i].s[0]*3;
p[i].a=40+p[i].s[0]*0.01+p[i].b*0.0001;
continue;
}
}
else if(p[i].s[2]==p[i].s[4]){
if(p[i].s[0]==p[i].s[1]){
p[i].a=50+p[i].s[2]*0.01+p[i].s[0]*0.0001;
continue;
}
else{
p[i].b-=p[i].s[2]*3;
p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
continue;
}
}
else if(p[i].s[0]==p[i].s[1]){
if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
p[i].b=p[i].b-p[i].s[0]*2-p[i].s[3]*2;
p[i].a=30+p[i].s[0]*0.01+p[i].s[3]*0.0001+p[i].b*0.000001;
continue;
}
else{
p[i].b-=p[i].s[0]*2;
p[i].a=20+p[i].s[0]*0.01+p[i].b*0.0001;
continue;
}
}
else if(p[i].s[1]==p[i].s[2]){
if(p[i].s[3]==p[i].s[4]){
p[i].a=30+p[i].s[1]*0.01+p[i].s[3]*0.0001+p[i].s[0]*0.000001;
continue;
}
else{
p[i].b-=p[i].s[1]*2;
p[i].a=20+p[i].s[1]*0.01+p[i].b*0.0001;
continue;
}
}
else if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
p[i].b-=p[i].s[3]*2;
p[i].a=20+p[i].s[3]*0.01+p[i].b*0.0001;
continue;
}
for(j=0;j<4;j++)
{
if(p[i].s[j]-p[i].s[j+1]!=1)break;
}
if(j==4){
p[i].a=70+p[i].s[0]*0.01;
continue;
}
else if(j==3&&p[i].s[4]==1&&p[i].s[0]==13){
p[i].a=80;
continue;
}
p[i].a=10+p[i].b*0.1;
}
qsort(p,N,sizeof(struct pai),cmp);
for(i=0;i<N;i++)
{
printf("%s\n",p[i].name);
}
return 0;
}
int cmp(const void *p1,const void *p2)
{
struct pai *c=(struct pai*)p1;
struct pai *d=(struct pai*)p2;
if(c->a!=d->a)return c->a<d->a?1:-1;
else {
if(strcmp(c->name,d->name)>0)return 1;
else return -1;
}
}
写此题解为了纪念我被这道题折磨的这几天(土拨鼠尖叫)啊啊啊啊啊啊啊啊
第一周PTA笔记 德州扑克题解的更多相关文章
- 20165326 java第一周学习笔记
第一周学习笔记 一.理论视频学习 1.Java的特点:简单.面向对象.平台无关 2.Java的开发步骤&简单的应用程序: 文本编辑器写入代码 命名类名.java,文件类型所有文件,编码ANSI ...
- 《Linux内核分析》第一周学习笔记
<Linux内核分析>第一周学习笔记 计算机是如何工作的 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/c ...
- linux内核分析第一周学习笔记
linux内核分析第一周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- 第一周 总结笔记 / 斯坦福-Machine Learning-Andrew Ng
课程主页:https://www.coursera.org/learn/machine-learning/home/welcome 收集再多的资料也没用,关键是要自己理解总结,做笔记就是一个归纳总结的 ...
- JS第一周学习笔记整理
目录 JS正式课第一周笔记整理 JS正式课第一周笔记整理 webstorm : 代码编辑器 浏览器: 代码解析器: Git : 是一个工具;用于团队协作开发项目管理代码的工具:在工作中用git.svn ...
- Linux内核分析——第一周学习笔记20135308
第一周 计算机是如何工作的 第一节 存储程序计算机工作模型 1.冯·诺依曼结构模型:冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构.程序指令存储地址和数据存储 ...
- 20135320赵瀚青LINUX内核分析第一周学习笔记
赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.概述 第一周的学习内容主 ...
- 20179223《Linux内核原理与分析》第一周学习笔记
第一周实验 尝试创建两个文件,用通配符查找这两个文件:在创建文件的时候,需要同时创建多个文件的方法运行. 根据作业要求,实现一个lilux命令. 根据作业要求添加一个用户loutest,使用sudo创 ...
- 第一周课堂笔记2th
上课笔记2th https://mubu.com/doc/2gxvIvVLG0(老师笔记网址) 1. python python运行过程 把源代码转化成字节码(机器不能识别) 也可能不产生py ...
随机推荐
- AngularJS的简单实用
Angular Js 的初步认识和使用 一: 1.模块化 定义模块和控制器 ng-app="myapp" controller=&qu ...
- 获取HTML网页中option标签元素的值
在进行表单元素的操作时,难免会遇到对option元素的挑选,下面的示例代码能够很好的获取到你option元素选择的值,如果要传递给后端,可通过ajax或者其他方式传递即可. 示例代码 <!doc ...
- 改头换面为哪般,最像Android的Windows——Win11升级安装体验
在过完了十一小长假之后,各位打工人.学僧党可期待的不仅仅是新一轮的工作,Windows11也在10月5日悄悄正式发布,正式版已经面向MSDN订阅用户开放下载. 作为微软金牌合作伙伴,本葡萄已在第一时间 ...
- 飞猪基于 Serverless 的云+端实践与思考
作者 | 王恒飞(承荫) 本文整理自飞猪旅行前端技术专家--王恒飞(承荫)在[阿里云 Serverless Developer Meetup 上海站]上的分享.点击查看直播回放:https://dev ...
- 人力节省 50%,研发效能提升 40%,阿里 Serverless 架构落地实践
作者 | 万佳 嘉宾 | 杨皓然(不瞋) 导读:云的下一波浪潮是什么?杨皓然称"是 Serverless".作为一名阿里老兵,他早在 2010 年即加入阿里云,曾深度参与阿里云飞天 ...
- 分布式全局ID与分布式事务
1. 概述 老话说的好:人不可貌相,海水不可斗量.以貌取人是非常不好的,我们要平等的对待每一个人. 言归正传,今天我们来聊一下分布式全局 ID 与分布式事务. 2. 分布式全局ID 2.1 分布式数据 ...
- 初学Python-day8 案例2
中奖率 1 import random 2 num = 123456 3 i = 1 4 while True: 5 win = random.randrange(100000, 999999) 6 ...
- 【Java虚拟机3】类加载器
前言 Java虚拟机设计团队有意把类加载阶段中的"通过一个类的全限定名来获取描述该类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类. ...
- Vue el 使用el-checkbox-group复选框进行单选框操作
el-checkbox-group这个组件与其他复选框不一样,我当初也是半天不知道怎么操作 页面使用v-model绑定 size就是等比例缩小放大,v-ror循环应该看的懂.重要的是@chage到我们 ...
- logstash multi pipeline的使用
logstash multi pipeline的使用 一.背景 二.解决方案 1.方案一: 2.方案二: 3.方案三: 三.实现步骤 1.编写 pipeline 文件 1.从文件收集,输出到控制台 2 ...