2021牛客OI赛前集训营-提高组(第三场) T4扑克

该文章介绍了一个基于扑克牌的游戏策略问题,玩家需要构想出能战胜对手的牌型。解决方案包括暴力枚举所有可能的五张牌组合,对它们进行排序,然后在给定对手的牌后,找出能获胜的最小牌。代码实现中涉及到数组处理、排序和特定情况的判断逻辑。
摘要由CSDN通过智能技术生成

2021牛客OI赛前集训营-提高组(第三场)

题目大意

小A和小B在玩扑克牌游戏,规则如下:

从一副52张牌(没有大小王)的扑克牌中随机发3张到每个玩家手上,每个玩家可以任意想象另外两张牌,与自己手上的牌组成5张牌,已构成最大的手牌。

两幅手牌比较大小的规则如下:

在这里插入图片描述
如果牌型一致,则按关键牌组来比较。

小A可以知道小B手中的牌。小A决定对于每一次游戏都想象出一副刚刚好能赢小B的牌。请你告诉小A这两张牌分别是什么,或告诉他无法取胜。


题解

注意事项

  • 玩家可以想象对方有的牌,但不能想象自己有的牌
  • 小A的牌要在能赢小B的基础上尽量小,如果有两种花色都能赢小B,则优先选择花色小的

一些简化

  • 因为无论三张牌如何,都至少可以通过想象得到三条,所以两对,一对和高牌可以不用考虑

做法

在不考虑花色的情况下,暴力枚举出所有五元组,五元组的数量并不多。然后将五元组排序,再求出所有三元组。

对于每次询问,将三元组对应的五元组进行比较,再考虑花色的影响,即可得出答案。

code

#include<bits/stdc++.h>
using namespace std;
int t,c1,vd,mxa,mxb,va,vb,sc,fl,ip[205],icl[205],z[20],zh[20],zp[10][20];
int tot=0,d[500005],l[500005],r[500005];
char op[20],ocl[10];
void add(int xx,int yy){
	l[++tot]=r[xx];d[tot]=yy;r[xx]=tot;
}
struct node{
	int x,y;
}a[10],b[10];
struct five{
	int val,sh,a[10];
}w,ans,v[50005];
void init(){
	for(int i=2;i<=9;i++){
		ip[i+'0']=i;op[i]=i+'0';
	}
	ip['T']=10;ip['J']=11;ip['Q']=12;ip['K']=13;ip['A']=14;
	op[10]='T';op[11]='J';op[12]='Q';op[13]='K';op[14]='A';
	icl['S']=4;icl['H']=3;icl['C']=2;icl['D']=1;
	ocl[4]='S';ocl[3]='H';ocl[2]='C';ocl[1]='D';
}
void dfs(int t,int now){
	for(int i=now;i<=14;i++){
		if(z[i]<4){
			w.a[t]=i;++z[i];
			if(t<5) dfs(t+1,i);
			else v[++vd]=w;
			--z[i];
		}
	}
}
bool four_of_a_kind(){
	if(w.a[2]==w.a[3]&&w.a[3]==w.a[4]){
		if(w.a[1]==w.a[2]||w.a[4]==w.a[5]) return 1;
	}
	return 0;
}
bool full_house(){
	if(w.a[1]==w.a[2]&&w.a[2]==w.a[3]&&w.a[4]==w.a[5]) return 1;
	if(w.a[1]==w.a[2]&&w.a[3]==w.a[4]&&w.a[4]==w.a[5]) return 1;
	return 0;
}
bool three_of_a_kind(){
	if(w.a[1]==w.a[2]&&w.a[2]==w.a[3]) return 1;
	if(w.a[2]==w.a[3]&&w.a[3]==w.a[4]) return 1;
	if(w.a[3]==w.a[4]&&w.a[4]==w.a[5]) return 1;
	return 0;
}
void gt(){
	if(w.a[1]+1==w.a[2]&&w.a[2]+1==w.a[3]&&w.a[3]+1==w.a[4]&&w.a[4]+1==w.a[5]) w.sh=1;
	if(four_of_a_kind()){
		w.val=7e8+w.a[3]*14;
		if(w.a[1]!=w.a[3]) w.val+=w.a[1];
		else w.val+=w.a[5];
	}
	else if(full_house()){
		if(w.a[3]==w.a[1]) w.val=6e8+w.a[3]*15+w.a[5];
		else w.val=6e8+w.a[3]*15+w.a[1];
	}
	else if(w.sh) w.val=4e8+w.a[1];
	else if(three_of_a_kind()){
		w.val=3e8+w.a[3]*15*15;
		if(w.a[1]==w.a[2]&&w.a[2]==w.a[3]) w.val+=w.a[5]*15+w.a[4];
		else if(w.a[2]==w.a[3]&&w.a[3]==w.a[4]) w.val+=w.a[5]*15+w.a[1];
		else w.val+=w.a[2]*15+w.a[1];
	}
}
int find(int w1,int w2,int w3){
	return w1*15*15+w2*15+w3;
}
int dd(int g1,int g2,int w1,int w2,int w3){
	if(g2<w1){
		swap(g2,w1);
		if(w1<w2){
			swap(w1,w2);
			if(w2<w3) swap(w2,w3);
		}
	}
	if(g1<g2){
		swap(g1,g2);
		if(g2<w1){
			swap(g2,w1);
			if(w1<w2){
				swap(w1,w2);
				if(w2<w3) swap(w2,w3);
			}
		}
	}
	if(w3+1==w2&&w2+1==w1&&w1+1==g2&&g2+1==g1) return 1e8+w3;
	return g1*15*15*15*15+g2*15*15*15+w1*15*15+w2*15+w3;
}
void pt(){
	for(int i=1;i<=4;i++) zh[i]=0;
	for(int i=2;i<=14;i++) z[i]=0;
	++z[a[1].y];++zh[a[1].x];++zp[a[1].x][a[1].y];
	++z[a[2].y];++zh[a[2].x];++zp[a[2].x][a[2].y];
	++z[a[3].y];++zh[a[3].x];++zp[a[3].x][a[3].y];
	for(int i=5;i>=1;i--){
		if(z[ans.a[i]]) --z[ans.a[i]];
		else{
			if(fl) zp[a[1].x][ans.a[i]]=1;
			else{
				for(int j=1;j<=4;j++){
					if(!zp[j][ans.a[i]]&&zh[j]<4){
						++zh[j];
						zp[j][ans.a[i]]=1;
						break;
					}
				}
			}
		}
	}
	for(int i=2;i<=14;i++){
		for(int j=4;j>=1;j--){
			if(zp[j][i]){
				printf("%c%c ",ocl[j],op[i]);
				zp[j][i]=0;
			}
		}
	}
}
int main()
{
	init();
	dfs(1,2);
	for(int i=1;i<=vd;i++){
		w=v[i];gt();
		v[i]=w;
		add(find(w.a[1],w.a[2],w.a[3]),i);
		add(find(w.a[1],w.a[2],w.a[4]),i);
		add(find(w.a[1],w.a[2],w.a[5]),i);
		add(find(w.a[1],w.a[3],w.a[4]),i);
		add(find(w.a[1],w.a[3],w.a[5]),i);
		add(find(w.a[1],w.a[4],w.a[5]),i);
		add(find(w.a[2],w.a[3],w.a[4]),i);
		add(find(w.a[2],w.a[3],w.a[5]),i);
		add(find(w.a[2],w.a[4],w.a[5]),i);
		add(find(w.a[3],w.a[4],w.a[5]),i);
	}
	char ch[5];
	scanf("%d",&t);
	while(t--){
		fl=sc=0;
		for(int i=1;i<=3;i++){
			scanf("%s",ch);
			a[i]=(node){icl[ch[0]],ip[ch[1]]};
		}
		if(a[1].x==a[2].x&&a[2].x==a[3].x) sc=1;
		for(int i=1;i<=3;i++){
			scanf("%s",ch);
			b[i]=(node){icl[ch[0]],ip[ch[1]]};
		}
		mxb=0;vb=0;
		int vt=find(b[1].y,b[2].y,b[3].y);
		for(int i=r[vt];i;i=l[i]){
			mxb=max(mxb,v[d[i]].val);
			vb|=v[d[i]].sh;
		}
		if(b[1].x==b[2].x&&b[2].x==b[3].x){
			int g1=0,g[20];
			for(int i=14;i>=2;i--){
				if(i!=b[1].y&&i!=b[2].y&&i!=b[3].y){
					g[++g1]=i;
					if(g1>=2) break;
				}
			}
			mxb=max(mxb,500000000+dd(g[1],g[2],b[3].y,b[2].y,b[1].y));
			if(vb){
				mxb=9e8+min(10,b[1].y);
				if(b[1].y==10) mxb=1e9;
			}
		}
		mxa=2e9;va=0;
		vt=find(a[1].y,a[2].y,a[3].y);
		for(int i=r[vt];i;i=l[i]){
			if(v[d[i]].val>mxb&&v[d[i]].val<mxa){
				mxa=v[d[i]].val;
				ans=v[d[i]];
			}
			va|=v[d[i]].sh;
		}
		if(a[1].x==a[2].x&&a[2].x==a[3].x){
			int g1=0,g[20];
			for(int i=14;i>=2;i--){
				if(i!=a[1].y&&i!=a[2].y&&i!=a[3].y) g[++g1]=i;
			}
			for(int i=1;i<=g1;i++){
				for(int j=i+1;j<=g1;j++){
					vt=5e8+dd(g[i],g[j],a[3].y,a[2].y,a[1].y);
					if(vt>mxb&&vt<mxa){
						mxa=vt;fl=1;
						ans.a[1]=a[1].y;
						ans.a[2]=a[2].y;
						ans.a[3]=a[3].y;
						ans.a[4]=g[j];
						ans.a[5]=g[i];
					}
				}
			}
			if(va){
				for(int i=min(10,a[1].y);i+4>=max(a[3].y,6);i--){
					vt=9e8+i;
					if(i==10) vt=1e9;
					if(vt>mxb&&vt<mxa){
						mxa=vt;fl=1;
						ans.a[1]=i;
						ans.a[2]=i+1;
						ans.a[3]=i+2;
						ans.a[4]=i+3;
						ans.a[5]=i+4;
	
					}
				}
			}
		}
		if(mxa==2e9) printf("-1");
		else pt();
		printf("\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值