D题: Poker Game: Decision

原题链接:https://ac.nowcoder.com/acm/contest/33193/D

题目大意

在德州扑克的大小比较规则情况下,发牌顺序与传统德扑不同。

初始发给Alice和Bob各两种手牌且双方均知道对方的手牌。牌桌上有 666 张牌。双方轮流选取一张牌,直到各有 555 张牌。Alice先手,牌组更大者获胜,求双方均采取最优策略的情况下,谁获胜。

德州扑克比较规则可参考:百度百科:德克萨斯扑克

题解

暴搜模拟然后基础博弈论转移即可,最麻烦的部分是大小比较。

关于牌型

不妨将同花和顺子(注意特判 A2345A2345A2345 )作为标记保存下来。
对于牌的点数可以保存入一个计数数组进行排序,方便知道第 iii 多的牌有多少张。

同牌型大小比较

1.皇家同花顺

只能是平局。

2.同花/高牌

排序后从大到小依次比较即可。

3.顺子/同花顺

首先特判最小的顺子 A2345A2345A2345 ,然后各自取最大的一张进行比较即可。

4.四张/葫芦/三张/两对/一对

不难发现这些牌型的比较都呈现 41/32/311/221/21114\ 1/3\ 2/3\ 1\ 1/2\ 2\ 1/2\ 1\ 1\ 14 1/3 2/3 1 1/2 2 1/2 1 1 1 的先比较张数多的牌的规律。
不妨重新利用计数数组,以张数为第一关键字,点数为第二关键字进行排序,然后从大到小依次比较即可。

两个优化

  1. 在搜索到必胜态时可以直接返回剪枝。
  2. 考虑操作序列有 6!6!6! 种,但是两个人得到牌的情况只有 C63C_6^3C63​ 种,可以状压记忆化Alice选了哪些牌。

参考代码

#include<bits/stdc++.h>
#define P pair<int,int>
using namespace std;template<class T>inline void read(T&x){char c,last=' ';while(!isdigit(c=getchar()))last=c;x=c^48;while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);if(last=='-')x=-x;
}map<char,int>mp;
void init()//字符转点数/花色
{mp['A']=14;mp['K']=13;mp['Q']=12;mp['J']=11;mp['T']=10;mp['9']=9;mp['8']=8;mp['7']=7;mp['6']=6;mp['5']=5;mp['4']=4;mp['3']=3;mp['2']=2;mp['1']=1;mp['S']=1;mp['H']=2;mp['C']=3;mp['D']=4;
}struct card{int num,suit;
};bool cmp(const card&a,const card&b){return a.num>b.num;}//根据点数从大到小struct cards{card c[5];void init(){sort(c,c+5,cmp);}
};int type(cards a){//获得牌型a.init();vector<int>cnt(15);//计数数组int is_flush=1,is_straight=0;//标记:是否为同花/顺子for(int i=0;i<5;++i){if(i<4)is_flush&=a.c[i].suit==a.c[i+1].suit;++cnt[a.c[i].num];}sort(cnt.begin(),cnt.end(),greater<int>());if(a.c[0].num==14&&a.c[1].num==5&&a.c[2].num==4&&a.c[3].num==3&&a.c[4].num==2)is_straight=1;//特判A2345if(a.c[0].num==a.c[1].num+1&&a.c[1].num==a.c[2].num+1&&a.c[2].num==a.c[3].num+1&&a.c[3].num==a.c[4].num+1)is_straight=1;if(is_flush&&is_straight&&a.c[4].num==14)return 1;//皇家同花顺if(is_flush&&is_straight)return 2;//同花顺if(cnt[0]==4)return 3;//四张if(cnt[0]==3&&cnt[1]==2)return 4;//葫芦if(is_flush)return 5;//同花if(is_straight)return 6;//顺子if(cnt[0]==3)return 7;//三张if(cnt[0]==2&&cnt[1]==2)return 8;//两对if(cnt[0]==2)return 9;//一对return 10;//高牌
}int cmp_royal(cards a,cards b){//皇家同花顺return 3;
}int cmp_regular(cards a,cards b){//同花/高牌a.init(),b.init();for(int i=0;i<5;++i){if(a.c[i].num>b.c[i].num)return 1;if(b.c[i].num>a.c[i].num)return 2;}return 3;
}int cmp_straight(cards a,cards b){//同花顺/顺子a.init(),b.init();int x=a.c[0].num==14&&a.c[4].num==2;//特判A2345是最小的顺子int y=b.c[0].num==14&&a.c[4].num==2;if(x&&y)return 3;if(x)return 2;if(y)return 1;x=a.c[0].num;y=b.c[0].num;if(x>y)return 1;if(y<x)return 2;return 3;
}int cmp_groups(cards a,cards b){//葫芦/四张/三张/两对/一对vector<P>suma(15),sumb(15);//计数数组for(int i=2;i<=14;++i)suma[i].second=sumb[i].second=i;//以点数为第二关键字for(int i=0;i<5;++i)++suma[a.c[i].num].first,++sumb[b.c[i].num].first;//以牌数为第一关键字sort(suma.begin(),suma.end());//std::pair在比较时默认先比第一关键字,再比第二关键字sort(sumb.begin(),sumb.end());for(int i=14,p1=0,p2=0;i>=2;--i){//从大到小重新整牌while(suma[i].first)a.c[p1++].num=suma[i].second,--suma[i].first;while(sumb[i].first)b.c[p2++].num=sumb[i].second,--sumb[i].first;}for(int i=0;i<5;++i){//比较if(a.c[i].num>b.c[i].num)return 1;if(b.c[i].num>a.c[i].num)return 2;}return 3;
}int cmp(cards a,cards b){//手牌比较int ta=type(a),tb=type(b);
//  cerr<<ta<<' '<<tb<<'\n';if(ta<tb)return 1;if(tb<ta)return 2;if(ta==1)return cmp_royal(a,b);if(ta==5||ta==10)return cmp_regular(a,b);if(ta==2||ta==6)return cmp_straight(a,b);if(ta==3||ta==4||ta==7||ta==8||ta==9)return cmp_groups(a,b);return 3;//这句话不会被调用,只适用于通过编译防止报错
}cards A,B;
card c[6];
int b[6];
int ans[100];//记忆化void debug(){//调试:输出手牌for(int i=0;i<5;++i){cerr<<A.c[i].num<<' '<<A.c[i].suit<<"  ";}puts("");for(int i=0;i<5;++i){cerr<<B.c[i].num<<' '<<B.c[i].suit<<"  ";}puts("");puts("");
}int dfs(int d,int p1,int p2,int bit){//bit为状压的Alice选取的牌if(d>6){//      debug();if(ans[bit])return ans[bit];//已经算过了return ans[bit]=cmp(A,B);}if(d&1){int f=0;for(int i=0;i<6;++i){if(b[i])continue;A.c[p1]=c[i];b[i]=1;int res=dfs(d+1,p1+1,p2,bit|1<<i);b[i]=0;if(res==1)return 1;//剪枝,注意放在b[i]=0回溯之后f|=res==3;}return f?3:2;//能平则平}else{int f=0;for(int i=0;i<6;++i){if(b[i])continue;B.c[p2]=c[i];b[i]=1;int res=dfs(d+1,p1,p2+1,bit);b[i]=0;if(res==2)return 2;//剪枝f|=res==3;}return f?3:1;}
}int main()
{init();int T;read(T);while(T--){memset(ans,0,sizeof(ans));//清空记忆化数组string s;for(int i=0;i<2;++i){cin>>s;A.c[i].num=mp[s[0]];A.c[i].suit=mp[s[1]];}for(int i=0;i<2;++i){cin>>s;B.c[i].num=mp[s[0]];B.c[i].suit=mp[s[1]];}for(int i=0;i<6;++i){cin>>s;c[i].num=mp[s[0]];c[i].suit=mp[s[1]];}int res=dfs(1,2,2,0);if(res==1)puts("Alice");if(res==2)puts("Bob");if(res==3)puts("Draw");}return 0;
}

“蔚来杯“2022牛客暑期多校训练营8 D题: Poker Game: Decision相关推荐

  1. “蔚来杯“2022牛客暑期多校训练营9 补题题解(A、B、G、E)

    "蔚来杯"2022牛客暑期多校训练营9 A Car Show B Two Frogs G Magic Spells E Longest Increasing Subsequence ...

  2. “蔚来杯“2022牛客暑期多校训练营10补题

    H  Wheel of Fortune 题意 有两个人在打炉石,一方转动了尤格萨隆的命运之轮触发了炎爆选项.双方英雄的血量分别为A和B,双方场面的血量分别为ai和bi,问A获胜的概率. 思路 将代码分 ...

  3. “蔚来杯“2022牛客暑期多校训练营7 L Maximum Range(强连通缩点+网络流输出方案)

    "蔚来杯"2022牛客暑期多校训练营7 L Maximum Range(强连通缩点+网络流输出方案) 题意 找一个环 上面的边权 极差最大 并输出 点 思路 我们先强联通缩点 统计 ...

  4. “蔚来杯“2022牛客暑期多校训练营1

    "蔚来杯"2022牛客暑期多校训练营1 C Grab the Seat! D Mocha and Railgun 题意: 给定一个圆环,中心为(0, 0).给定T个查询,每次给定环 ...

  5. “蔚来杯“2022牛客暑期多校训练营6

    "蔚来杯"2022牛客暑期多校训练营6 [题目链接]("蔚来杯"2022牛客暑期多校训练营6_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛 ...

  6. “蔚来杯“2022牛客暑期多校训练营10,签到题HFIE

    题号 标题 已通过代码 通过率 团队的状态 A Everlasting Transeunt 点击查看 6/42 B Fall Guys-Perfect Match 点击查看 6/115 C Magic ...

  7. “蔚来杯“2022牛客暑期多校训练营8

    Equivalence in Connectivity 前置知识点如下: 1. 并查集哈希 2. 可撤销并查集 3. 线段树分治 #include<bits/stdc++.h> using ...

  8. “蔚来杯“2022牛客暑期多校训练营2 G.[Link with Monotonic Subsequence] 分块构造

    G. Link with Monotonic Subsequence 构造 题目分析 要求构造一个长度为 n n n的序列,使得序列的 max ⁡ ( lis ( p ) , lds ( p ) ) ...

  9. “蔚来杯“2022牛客暑期多校训练营2 个人题解集合

    文章目录 D.[Link with Game Glitch](https://ac.nowcoder.com/acm/contest/33187/D) 题目分析 Code G.[ Link with ...

最新文章

  1. 面试题--特别是字节对齐
  2. scss里父选择器的标识符
  3. beeline连接hiveserver2报错:User: root is not allowed to impersonate root
  4. Groovy新手教程
  5. 图像处理常用八大算法
  6. window下移动设备/硬盘报错位置不可用
  7. 兼容ie\firefox\chrome的cursor
  8. 花生壳配置内网穿透,ssh远程登录
  9. 近世代数课后习题作业 1
  10. 趣味点名软件_网传川大教授用刷脸软件点名 无人逃课
  11. 人工神经网络的数学内涵,神经网络的数学表达式
  12. 执行引擎的工作过程、Java代码编译和执行的过程、解释器、JIT编译器
  13. treecnt 51Nod - 1677
  14. apollo如何添加第三方库,以pylon为例
  15. 【机器学习入门】决策树算法(四):CART算法(Classification and Regression Tree)
  16. Sailfish应用开发入门(二)Sailfish SDK 简介
  17. 打造产业的“喀秋莎”(上)——什么是我们要的“事实标准”
  18. markdown编辑简介
  19. 用 JMeter 进行压力测试
  20. 新闻发布会--联想笔记本

热门文章

  1. MySQL之——MS主从复制(读写分离)实现
  2. 国内微博先驱与烈士——饭否网
  3. 基于元学习和自我监督的图像翻译预训练
  4. Maven 虐我千百遍,我待 Maven 如初恋 侵删
  5. KgoUI(2) 之 vue + layui
  6. LeetCode:面试题 01.02. 判定是否互为字符重排————简单
  7. 10.4.变态跳楼梯
  8. 计算机房英语单词,计算机与网络英语词汇(O1)
  9. 程序员需要了解的.NET Framework 编程的好与坏
  10. 用python画名字组成的爱心_520用Python画一颗特别的爱心送给她