D Poker Game: Decision
题意:桌面上有 张扑克牌,Alice 和 Bob 手上各有 张且明牌。二人以最优决策依次从桌上抽取一张牌直到二人各有五张牌,最终根据德州扑克的规则比大小。问最终谁会赢。
解法:首先写清楚德州扑克的大小比较:依次按照牌型从大到小的顺序看能否构成这一种牌型。由于此处张数较少,可以暴力枚举每一种抽牌情况,暴力 dfs 计算当前的最优决策。设 dfs 返回值为 为 Bob 胜利、平局、Alice 胜利,Alice 会从中选择尽可能大的状态转移,而 Bob 会选择最小的。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define pb push_back
#define abs(x,y) (x<y?y-x:x-y)
using namespace std;
const int N=5e4+3,M=5e4+3;
struct kk{
int op,r;
bool operator<(const kk &a) const{
return r>a.r;
}
}a[3],b[3],c[10];
struct hh{//比较牌的大小
int rk;kk a[6];
int operator<(const hh &b) const{
if(rk^b.rk) return rk<b.rk;
for(int i=1;i<=5;++i)
if(a[i].r^b.a[i].r) return a[i].r<b.a[i].r;
return 2;
}
void get_rk(){
sort(a+1,a+6);kk b[6];
int f1=1,f2=1;
for(int i=2;i<=5;++i) if(a[i].op^a[i-1].op) f1=0;
for(int i=2;i<=5;++i) if(a[i].r^a[i-1].r-1) f2=0;
if(f1&&f2&&a[1].r==13) rk=12;
else if(f1&&f2) rk=11;
else if(f1&&a[1].r==13&&a[2].r==4&&a[3].r==3&&a[4].r==2&&a[5].r==1) rk=10;
else if(a[1].r==a[2].r&&a[2].r==a[3].r&&a[3].r==a[4].r) rk=9;
else if(a[2].r==a[3].r&&a[3].r==a[4].r&&a[4].r==a[5].r) rk=9,swap(a[1],a[5]);
else if(a[1].r==a[2].r&&a[2].r==a[3].r&&a[4].r==a[5].r) rk=8;
else if(a[1].r==a[2].r&&a[3].r==a[4].r&&a[4].r==a[5].r) rk=8,swap(a[1],a[5]),swap(a[2],a[4]);
else if(f1) rk=7;
else if(f2) rk=6;
else if(a[1].r==13&&a[2].r==4&&a[3].r==3&&a[4].r==2&&a[5].r==1) rk=5;
else if(a[1].r==a[2].r&&a[2].r==a[3].r) rk=4;
else if(a[2].r==a[3].r&&a[3].r==a[4].r) rk=4,swap(a[1],a[2]),swap(a[2],a[3]),swap(a[3],a[4]);
else if(a[3].r==a[4].r&&a[4].r==a[5].r){
rk=4;for(int i=1;i<=5;++i) b[i]=a[i];
a[1]=b[3],a[2]=b[4],a[3]=b[5],a[4]=b[1],a[5]=b[2];
}
else if(a[1].r==a[2].r&&a[3].r==a[4].r) rk=3;
else if(a[1].r==a[2].r&&a[4].r==a[5].r) rk=3,swap(a[3],a[5]);
else if(a[2].r==a[3].r&&a[4].r==a[5].r){
rk=3;for(int i=1;i<5;++i) swap(a[i],a[i+1]);
}
else if(a[1].r==a[2].r) rk=2;
else if(a[2].r==a[3].r) rk=2,swap(a[1],a[3]);
else if(a[3].r==a[4].r) rk=2,swap(a[1],a[3]),swap(a[2],a[4]);
else if(a[4].r==a[5].r){
rk=2;for(int i=1;i<=5;++i) b[i]=a[i];
a[1]=b[4],a[2]=b[5],a[3]=b[1],a[4]=b[2],a[5]=b[3];
}
else rk=1;
}
}A,B,na,nb;
int cn,to[129];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL void get(kk &a){
char s[4];scanf("%s",s+1);
a.op=to[s[2]],a.r=to[s[1]];
}
int bo[10],mp[800],pm[100];
IL int cmp(hh a,hh b){
a.get_rk(),b.get_rk();
int x=b<a;
if(!x) return 0;
if(x==1) return 2;
return 1;
}
int dfs(int pos,int val){//暴力搜索
if(~mp[val]) return mp[val];
if(pos==7) return mp[val]=cmp(na,nb);
mp[val]=pos&1?0:2;
for(int i=1;i<=6;++i)
if(!bo[i]){
int now=val;
if(pos&1) na.a[(pos+1>>1)+2]=c[i],now+=pm[i-1];
else nb.a[(pos>>1)+2]=c[i],now+=pm[i-1]*2;
bo[i]=1;
int op=dfs(pos+1,now);
bo[i]=0;
if(pos&1) mp[val]=max(mp[val],op);
else mp[val]=min(mp[val],op);
}
return mp[val];
}
IL void solve(){
na.rk=nb.rk=0;memset(mp,-1,sizeof(mp));
get(na.a[1]),get(na.a[2]),get(nb.a[1]),get(nb.a[2]);
for(int i=1;i<=6;++i) get(c[i]);
int ans=dfs(1,0);
if(!ans) puts("Bob");
else if(ans==1) puts("Draw");
else puts("Alice");
}
int main()
{
pm[0]=1;for(int i=1;i<=6;++i) pm[i]=pm[i-1]*3;
to['S']=1,to['H']=2,to['C']=3,to['D']=4;
to['A']=13,to['2']=1,to['3']=2,to['4']=3,to['5']=4,to['6']=5,to['7']=6,to['8']=7,to['9']=8,
to['T']=9,to['J']=10,to['Q']=11,to['K']=12;
int T=in();
while(T--) solve();
return 0;
}