yzoj 2377 颂芬梭哈 题解
题意
Alice 和 Mukyu 最近偶然得到了一本写有一种叫做梭哈的扑克游戏的规则的说明书(名为《C████████nd》,中间部分被涂掉了),据其所述,梭哈是一种使用黑桃、红心、梅花、方片的 A 到 K 共 52 张牌(没有大小王)来进行的扑克牌游戏。
不幸的是,规则说明中有关整个游戏的进行方式的部分被撕掉了,Alice 和 Mukyu 从残存的部分只得知了“手牌上限是 5 张”这一消息,所以他们决定每次直接给两人各发 5 张牌,判定谁的手牌比较大,说明书中关于手牌大小判定的信息如下:
所有五张牌的组合,按以下秩序,由大至小排行分为不同牌型:
1、同花顺(Straight Flush):同一花色,顺序的牌。 例: Q♦ J♦ 10♦ 9♦ 8♦;
2、四条(Four of a Kind):有四张同一点数的牌。 例: 10♣ 10♦ 10♥ 10♠ 9♥;
3、满堂红(Full House):三张同一点数的牌,加一对其他点数的牌。 例: 8♣ 8♦ 8♠ K♥ K♠;
4、同花(Flush):五张同一花色的牌。 例: A♠ K♠ 10♠ 9♠ 8♠;
5、顺子(Straight):五张顺连的牌。 例: K♦ Q♥ J♠ 10♦ 9♦;
6、三条(Three of a kind):有三张同一点数的牌。 例: J♣ J♥ J♠ K♦ 9♠;
7、两对(Two Pairs):两张相同点数的牌,加另外两张相同点数的牌。 例: A♣ A♦ 8♥ 8♠ Q♠;
8、一对(One Pair):两张相同点数的牌。 例: 9♥ 9♠ A♣ J♠ 8♥;
9、无对(Zilch):不能排成以上组合的牌,以点数决定大小。例: A♦ Q♦ J♠ 9♣ 8♣。
若牌型一样则利用点数和花色决定胜负。(点数优先)
点数的顺序(从大至小)为:A>K>Q>J>10>9>8>7>6>5>4>3>2。(注:当 5 张手牌是 5 4 3 2 A 的时候,A 可以看作最小的牌,此时的牌型仍然为顺子,是顺子里面最小的一个)。
花色的顺序(大至小)为:黑桃(♠)>红心(♥)>梅花(♣)>方块(♦)。
举例说明:
1、Q♦ J♦ 10♦ 9♦ 8♦ > 8♣ 8♥ 8♠ K♥ K♠ (前者牌型为同花顺,比后者大);
2、9♣ 9♦ 9♠ Q♥ Q♠ > 8♣ 8♦ 8♠ K♥ K♠ (两者牌型均为满堂红,比较牌型中三张同一点数的牌 9 比 8 大);
3、A♣ A♦ 8♥ 8♠ Q♠ > A♠ A♥ 7♥ 7♠ K♠ (两者牌型均为两对,且最大的对子相同,此时比较次大的对子,8 比 7 大);
4、A♠ Q♠ J♥ 9♥ 8♥ > A♦ Q♦ J♠ 9♣ 8♣ (两者牌型均为无对,所有数码均相同,此时比较最大牌的花色,A♠ > A♦)。
5、4♠ 4♥ A♦ Q♦ 5♦ > 4♣ 4♦ A♠ Q♠ 5♠ (两者牌型均为一对,所有数码均相同,此时对 4 为牌型里最大的部分,因此比较 4♠ > 4♣)
”
尽管 Alice 和 Mukyu 都可以轻易的判断出结果,他们还是想见识一下现代科技的力量。
输入格式
第一行包含一个正整数 N,表示有 N 组测试数据。
每组测试数据包含 10 行,前 5 行每行用两个整数描述一张 Alice 手上的牌,第一个数表示牌的数码(1 表示 A,13 表示 K),第二个数表示牌的花色(1 表示黑桃,2 表示红心, 3 表示梅花,4 表示方块)。
后 5 行每行用两个整数描述 Mukyu 手上的牌,格式同上。
输出格式
对于每组测试数据,在单独的一行内输出 Alice 或 Mukyu,表示谁能赢。
样例输入
1
1 3
5 3
4 3
3 3
2 3
6 1
10 4
7 1
8 1
9 2
样例输出
Alice
样例解释
Alice 的手牌构成同花顺,而 Mukyu 的手牌仅构成普通顺子。
数据范围
对于 10%的数据,保证输入的全部牌型都是无对。
对于另外 30%的数据,保证输入的全部牌型都是顺子、同花或同花顺。
对于 100%的数据,保证 N ≤ 100000。
C++选手如果使用 cin 读入数据很可能因此超时,推荐使用 scanf/printf。
解析
一道大模拟,按照题意模拟即可,细节还是蛮多的,讲下大致思路,
1.先按照点数降序排序后我们可以按照5张牌中花色的种类和点数的种类以及出现最多的相同点数的次数分类,先找出牌型和其中最大的一张牌的点数,我们可以根据上面的参数分辨大部分牌型。
我们用mcol表示花色种类,mdata表示点数种类,mcom表示出现最多的相同点数的次数。
四条: mcol4&&mdata2&&mcom==4
满堂红:mcol>=3&&mdata2&&mcom3
三条:mcol>=3&&mdata3&&mcom3
两对:mcol>=2&&mdata3&&mcom2
一对:mcol>=2&&mdata4&&mcom2
顺子:mcol>=1&&mdata5&&mcom0(其中可能出现无对
同花顺,同花:mcol1&&mdata5&&mcom==0
其中只需细分顺子,同花顺,同花,剩下的就是无对。
2.按照题意特殊处理 $ A $即可。 $ A $ 可以和 $ 2 3 4 5 $ 组成顺子,也可以和 $ 10 J Q K $ 组成顺子,并且在四条,满堂红,三条,两对,一对,同花的时候要把 $ 1->A $ 此处记得特判。
3.值得注意的是这道题的判断比较稍微麻烦一些,因为它需要先比较牌型的点数而不是最大一张牌的点数,所以较为麻烦,下面详细解释一下。
顺子,同花顺:对于顺子我们可以直接比较上面求到的最大的一张牌的点数和花色,因为我们知道顺子是连续的,所以说如果最大的一张牌的点数相同他们所以数码就一定相同。
四条,满堂红,三条:直接判断最中间的点数,排完序后,三/四张相同的一定在中间,因为只有52张牌,所以不肯能出现点数相同的情况,所以直接比较点数即可。
同花:倒序枚举每张牌的点数,如果码数相同比较花色,因为52张牌所以花色必不可能相同。
两对:找出其中的两个对子,先比较较大的对子的点数,再比较较小的对子的点数,如果还是相同再比较最后一张单牌的点数,最后比较较大对子的点数,同理只有52张牌,所以如果码数相同那么花色必然不可能相同。
单对:同理先找出对子,比较对子点数,再比较单牌点数,最后比较对子花色
无对:倒序枚举判断每一张单牌点数,最后判断最大一张的花色。
代码
#include<bits/stdc++.h>
using namespace std;
struct node{
int data;//点数
int col;//花色
}b[10],c[20];
struct Node{
int data;//点数
int col;//花色
int num;//种类
};
int n,ans;
bool cmp(node a,node b){
return a.data<b.data;
}
node find(node a[]){
int maxcol=0;//最大花色
int maxdata=0;//最大点数
node p;
for(int i=5;i>=1;--i){//逆过来!
if(a[i].data>=maxdata){
maxdata=a[i].data;
maxcol=max(a[i].col,maxcol);
}
}
p.data=maxdata;
p.col=maxcol;
return p;
}
Node cheak(node a[]){
int mdata=0;//点数种类
int mcol=0;//花色种类
int mcom=0;//某个点数出现最多的次数
int book[20];
memset(book,0,sizeof(book));
for(int i=1;i<=5;++i){//找花色种类
if(!book[a[i].col]){
book[a[i].col]=1;
mcol++;
}
}
memset(book,0,sizeof(book));
for(int i=1;i<=5;++i){//找点数种类 及 次数
if(!book[a[i].data]){
book[a[i].data]++;
mdata++;
}else{
book[a[i].data]++;
mcom=max(mcom,book[a[i].data]);
}
}
if(mcol==4&&mdata==2&&mcom==4){//四条,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=2;
return ans;
}
else if(mcol>=3&&mdata==2&&mcom==3){//满堂红,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=3;
return ans;
}
else if(mcol>=3&&mdata==3&&mcom==3){//三条,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=6;
return ans;
}
else if(mcol>=2&&mdata==3&&mcom==2){//两对,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=7;
return ans;
}
else if(mcol>=2&&mdata==4&&mcom==2){//一对,把1换成A无影响
for(int i=1;i<=5;++i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=8;
return ans;
}
else if(mcol>=1&&mdata==5&&mcom==0){//同花顺,同花,顺子
if(mcol>1){//顺子
bool flag=1;
for(int i=2;i<5;++i){//判断2-5是不是连着的
if(a[i+1].data!=a[i].data+1) flag=0;
}
if(flag){
bool tmp=1;
for(int i=2;i<=5;++i){//判断是不是10-A
if(a[i].data!=i+8)tmp=0;
}
if((a[2].data==a[1].data+1)||(tmp&&a[1].data==1)) flag=1;//是不是顺子
else flag=0;
}
if(!flag){//无对特判
for(int i=5;i>=1;--i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=9;
return ans;
}
node tmp=find(a);
Node ans;
ans.col=tmp.col;
if(a[1].data==1&&a[2].data!=2){//判断是不是10-A
ans.data=14;
ans.col=a[1].col;
}
else ans.data=tmp.data;
ans.num=5;
return ans;
}else{
bool flag=1;
for(int i=1;i<5;++i){//判断2-5是不是连着的
if(a[i+1].data!=a[i].data+1) flag=0;
}
if(flag){
bool tmp=1;
for(int i=2;i<=5;++i){//判断是不是10-A
if(a[i].data!=i+8) tmp=0;
}
if((a[2].data==a[1].data+1)||(tmp&&a[1].data==1)) flag=1; //是不是顺子
else flag=0;
}
if(flag){//同花顺
node tmp=find(a);
Node ans;
ans.col=tmp.col;
if(a[1].data==1&&a[2].data==2) ans.data=1;
else if(a[1].data==1) ans.data=14;
else ans.data=tmp.data;
ans.num=1;
return ans;
}
else{//同花
for(int i=1;i<=5;++i){//把1换成A无影响
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=4;
return ans;
}
}
}
else{//无对
for(int i=5;i>=1;--i){
if(a[i].data==1) a[i].data=14;
}
sort(a+1,a+6,cmp);
node tmp=find(a);
Node ans;
ans.col=tmp.col;
ans.data=tmp.data;
ans.num=9;
return ans;
}
}
bool judge(Node x1,Node y1){//判断谁赢
if(x1.num<y1.num) return true;
else if(x1.num>y1.num) return false;
else{
if(x1.num==2||x1.num==3||x1.num==6){//四条,满堂红,三条特判
return b[3].data>c[3].data;//一定在中间 且不需要比较花色
}
if(x1.num==4){//同花特判
for(int i=5;i>=1;--i){//单牌比较
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(x1.col>y1.col) return true;
else return false;
}
if(x1.num==7){//两对特判
int tmp1=0;
int tmp2=0;
int tmp3=0;
int tmp4=0;
for(int i=1;i<5;++i){//第一副牌的两个对子
if(b[i].data==b[i+1].data){
if(!tmp1)tmp1=i;
else tmp3=i;
}
if(c[i].data==c[i+1].data){//第二幅牌
if(!tmp2)tmp2=i;
else tmp4=i;
}
}
if(b[tmp1].data<b[tmp3].data) swap(tmp1,tmp3);//保证1,2更大
if(b[tmp2].data<b[tmp4].data) swap(tmp2,tmp4);
if(b[tmp1].data>c[tmp2].data) return true;//第一大的对子比较
else if(b[tmp1].data<c[tmp2].data) return false;
else{
if(b[tmp3].data>c[tmp4].data) return true;//第二大的对子比较
else if(b[tmp3].data<c[tmp4].data) return false;
else{
for(int i=5;i>=1;--i){//单牌比较
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(max(b[tmp1].col,b[tmp1+1].col)>max(b[tmp2].col,b[tmp2+1].col)) return true;//数码相同,颜色比较
else return false;
}
}
}
else if(x1.num==8){//单对特判
int tmp1=0;
int tmp2=0;
for(int i=1;i<5;++i){//找对子
if(b[i].data==b[i+1].data) tmp1=i;
if(c[i].data==c[i+1].data) tmp2=i;
}
if(b[tmp1].data>c[tmp2].data) return true;
else if(b[tmp1].data<c[tmp2].data) return false;
else{
for(int i=5;i>=1;--i){
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(b[tmp1].col>c[tmp2].col) return true;
else return false;
}
}
else if(x1.num==9){//散牌
for(int i=5;i>=1;--i){
if(b[i].data>c[i].data) return true;
else if(b[i].data==c[i].data) continue;
else return false;
}
if(b[5].col>c[5].col) return true;//因为把A换成13所以比较最后一个
else return false;
}
else{//顺子可直接判断
if(x1.data>y1.data) return true;
else if(x1.data<y1.data) return false;
else{
if(x1.col>y1.col) return true;
else return false;
}
}
}
}
int main(){
//freopen("ptgiving.in","r",stdin);
//freopen("ptgiving.out","w",stdout);
scanf("%d",&n);
while(n--){
for(int i=1;i<=5;++i){
scanf("%d %d",&b[i].data,&b[i].col);
b[i].col=5-b[i].col;//转化花色
}
sort(b+1,b+6,cmp);
Node tmp1=cheak(b);
for(int i=1;i<=5;++i){
scanf("%d %d",&c[i].data,&c[i].col);
c[i].col=5-c[i].col;//转化花色
}
sort(c+1,c+6,cmp);
Node tmp2=cheak(c);
if(judge(tmp1,tmp2)) printf("Alice\n");
else printf("Mukyu\n");
}
return 0;
}
yzoj 2377 颂芬梭哈 题解的更多相关文章
- yzoj P2045 不老的传说 题解
题意 类似于涂色问题,环形问题不多说,断环加倍即可,限制条件if判断就行. 解析 代码 #include<bits/stdc++.h> using namespace std; int n ...
- yzoj 1201数字三角形3题解
题意 如下图所示为一个数字三角形: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 请编程计算从顶至底部某处的一条路径,使该路径所经过的数字的总和最大.约定: (1)每一步可沿直线向下或右 ...
- [SinGuLaRiTy] Nescafe 24杯模拟赛
[SinGularLaRiTy-1044] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 小水塘(lagoon) 题目描述 忘川沧月的小水塘 ...
- 洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】
可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊.. 题目描述 给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求: \[ ...
- yzoj P1126 塔 题解
题意:给n个积木,搭成两个高度相同的塔,问最高高度 正解是dp 答案在dp[n][0] 代码 #include<bits/stdc++.h> using namespace std; in ...
- yzoj P2043 & 洛谷 P1282 多米诺骨牌 题解
题意 类似于就是背包. 解析 代码 跟解析有点不一样v[i]价值,w[i]重量,s背包容积,背包转移即可. #include<bits/stdc++.h> using namespace ...
- yzoj P2044 数字游戏 题解
题意 dfs骗了30分,一开始想的距离正解差一点啊,贪心加dp就可以过的水题,真正太蒻了 解析 代码 #include<bits/stdc++.h> using namespace std ...
- 洛谷P1661 & yzoj 1650 扩散 题解
题意 先讲一下一种容易陷入误区错误思路 要使时间最小,就去找相对于每个点的最短曼哈顿距离,然后取最大值,时间就是(maxn+1)/2. 代码 #include<cstring> #incl ...
- yzoj P1412 & 洛谷P1629 邮递员送信 题解
有一个邮递员要送东西,邮局在结点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每次只能带一 ...
随机推荐
- struts的带参数结果集
action在forward过程中共享一个值栈,也就是一次request只有一个值栈,服务器端的forward对于客户端来说就是一次request,在forward过程就没必要再传参数了. 总结也就是 ...
- 基于Redis的分布式锁到底安全吗(上)?
基于Redis的分布式锁到底安全吗(上)? 2017-02-11 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词“Redis 分布式锁”随便到哪个搜索引擎上去搜索一下就知道了 ...
- springcloud config自动刷新中文乱码问题
摘录一段网上盛传的,如下: 在使用 spring cloud config 时,如果在 properties 文件里面有中文的话,会出现乱码. 乱码的原因是:spring 默认使用org.spring ...
- Thingsboard Docker关闭后重启服务创建network出错
因为个人想验证一下thingsboard的数据是否是保存在postgres中,就将postgres容器停止,后想重启则无法重启 我干脆将整个系统删除后重新再来一次,在试的时候发现无法重新创建容器 Cr ...
- essential
essential - 必应词典 美[ɪ'senʃ(ə)l]英[ɪ'senʃ(ə)l] n.要点:要素:实质:必需品 adj.完全必要的:必不可少的:极其重要的:本质的 网络基本的:必需的 变形复数: ...
- oracle tablespace pctfree pctused
二.oracle pctfree和pctused详解 一.建立表时候,注意PCTFREE参数的作用 PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示 ...
- python命令行传入参数
1.sys import sys a=eval(sys.argv[1])b=eval(sys.argv[2]) print(a+b) 1 2 3 4 5 6 evel() ...
- dubbo线程模型配置
首先了解一下dubbo线程模型 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识.则直接在IO线程上处理更快,因为减少了线程池调度. 但如果事件处理逻辑较慢,或者需要发 ...
- MQTT 客户端应用及常见问题(C#)
https://blog.csdn.net/dengyaan/article/details/51752327 最近因为工作需要,需要使用C# 语言编写一个通过MQTT协议 ,上传数据到云端的工具.因 ...
- MySQL 5.6&5.7 性能优化 TOP10(转)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/NLOneDay/article/deta ...