[博弈论][dfs]Poker Game:Decision 2022牛客多校第8场 D

10 篇文章 0 订阅
6 篇文章 0 订阅

题目描述

Alice and Bob invent a new game based on texas hold'em. Please read the following rules carefully as they are different from the usual rules. The background of this problem is exactly the same as problem E.

There are 131313 ranks, which are A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, and 2 from high to low. There are 444 suits, which are S, H, C, and D. Every combination of a rank and a suit occurs exactly once, so there are 525252(=13×4=13\times 4=13×4) cards.

A hand is a set of five cards. Each hand has a rank. There are 101010 types of hands. Each type also has a rank. If two hands are of different types, the hand of the type with a higher rank always ranks higher. A hand can be represented as a sequence (r1,r2,r3,r4,r5)(r_1,r_2,r_3,r_4,r_5)(r1​,r2​,r3​,r4​,r5​), where rir_iri​ is the rank of the iii-th card and the order of the five cards depends on the type of the hand. If two hands are of the same type, the hand represented as the lexicographically larger sequence ranks higher, i.e., find the smallest index iii such that rir_iri​ of two hands are different, the hand with higher rir_iri​ ranks higher. If the types and the sequences rrr of two hands are equal, two hands have the same rank.

The 101010 types are given in the following from low rank to high rank. If a hand matches the patterns of multiple types, it belongs to the one with the highest rank of them.

  • Highcard: Any five cards. The sequence rrr satisfies that r1>r2>r3>r4>r5r_1>r_2>r_3>r_4>r_5r1​>r2​>r3​>r4​>r5​.
  • Pair: Two cards with the same rank. The sequence rrr satisfies that r1=r2r_1=r_2r1​=r2​, r3>r4>r5r_3>r_4>r_5r3​>r4​>r5​.
  • Two pairs: Two cards with the same rank and another two cards with the same rank. The sequence rrr satisfies that r1=r2>r3=r4r_1=r_2>r_3=r_4r1​=r2​>r3​=r4​.
  • Three of a kind: Three cards with the same rank. The sequence rrr satisfies that r1=r2=r3r_1=r_2=r_3r1​=r2​=r3​, r4>r5r_4>r_5r4​>r5​.
  • Straight: Five cards with five consecutive ranks. The sequence rrr satisfies that r1>r2>r3>r4>r5r_1>r_2>r_3>r_4>r_5r1​>r2​>r3​>r4​>r5​. Especially, A 2 3 4 5 is a straight, and A is regarded as a rank lower than 2 in the situation. Hence A 2 3 4 5 is the straight with the lowest ranks.
  • Flush: Five cards with the same suit. The sequence rrr satisfies that r1>r2>r3>r4>r5r_1>r_2>r_3>r_4>r_5r1​>r2​>r3​>r4​>r5​.
  • Full house: Three cards with the same rank and another two cards with the same rank. The sequence rrr satisfies that r1=r2=r3r_1=r_2=r_3r1​=r2​=r3​, r4=r5r_4=r_5r4​=r5​.
  • Four of a kind: Four cards with the same rank. The sequence rrr satisfies that r1=r2=r3=r4r_1=r_2=r_3=r_4r1​=r2​=r3​=r4​.
  • Straight flush: A straight with the same suit. The sequence rrr satisfies that r1>r2>r3>r4>r5r_1>r_2>r_3>r_4>r_5r1​>r2​>r3​>r4​>r5​. Especially, A 2 3 4 5 with the same suit is a straight flush, and A is regarded as a rank lower than 2 in the situation. Hence A 2 3 4 5 with the same suit is the straight flush with the lowest ranks.
  • Royal flush: Straight flush with the ranks T, J, Q, K, and A. Four different royal flushes are of the same rank.

Two cards are dealt to each of Alice and Bob. Instead of the regular rule, 666 community cards are dealt. Two players take one card from the community cards in turn until each player has five cards, also a hand. Alice takes first. The player who has a hand with higher ranks wins. If two hands are with the same rank, there is a draw. Note that all ten cards are shown to both, and they always choose the optimal strategy.

The above are the same as problem E. The task is the following.

Given the cards of Alice, the cards of Bob and the 666 community cards, find the winner.

输入描述:

There are multiple test cases. The first line of input contains an integer TTT(1≤T≤1051\le T\le 10^51≤T≤105), the number of test cases. For each test case:

The first line contains two strings a1a_1a1​, a2a_2a2​ -- Alice's hole cards.

The second line contains two strings b1b_1b1​, b2b_2b2​ -- Bob's hole cards.

The third line contains 666 strings c1c_1c1​, c2c_2c2​, c3c_3c3​, c4c_4c4​, c5c_5c5​, c6c_6c6​ -- the community cards.

Each string is of length two. The first character is one of ”A”, ”K”, ”Q”, ”J”, ”T”, ”9”, ”8”, ”7”, ”6”, ”5”, ”4”, ”3”,”2”, which represents the rank of a card. The second character is one of ”S”, ”H”, ”C”, ”D”, which represents the suit of a card.

It is guaranteed that any two of the 101010 cards are different.

输出描述:

For each test case:

Output a string, one of ”Alice”, ”Bob”, ”Draw” -- representing that Alice wins, that Bob wins, and that there is a draw separately.

示例1

输入

9
JC 4H
TS 5D
JS JH JD 4S 4C 4D
JC 4H
TS 5D
TH TC TD 5S 5H 5C
JC 4H
TS 5D
4S JS 5S TH TC TD
7C 3C
7H TH
3S 3H 3D 2C 4H 5S
7C 3C
7H TH
2H 4H 5H 6H 8H 9H
7C 3C
7H TH
TS 3S 2S 2H 4C 4D
2D KH
4D JC
2S 2H 2C KS KC KD
2D KH
4D JC
4S 4H 4C JS JH JD
2D KH
4D JC
2S KS 4S JS JH JD

输出

Alice
Bob
Draw
Alice
Bob
Draw
Alice
Bob
Draw

题意: Alice和Bob打德州扑克,开始时两人各有两张牌,之后轮流从6张牌构成的牌堆中抽牌,最终两人均有5张牌,根据题目给定的规则比较这5张牌大小,若两人能够看到各自的牌和牌堆中的牌,且以最优策略进行游戏,问最终胜者是谁。

分析: 由于状态一共就6!个,所以可以暴力搜索,首先预处理出来最终alice不同选牌下的结果,也就是C(6, 3) = 20种方案,之后就可以dfs了,当选到第7轮时也就是两人都选够5张牌的时候直接返回刚才处理的结果,其实时候可以看子状态中是否有能让当前做选择的人胜利的状态,如果有的话那当前状态他赢,如果没有就找一个能达到平局的状态,如果还没有那当前状态他会输。

预处理的时候有几个坑点,首先是不同花色的A K Q J T也算是顺子,然后是对于特殊情况下的顺子要特殊处理,也就是5 4 3 2 A这种的。别的坑就没大有了,关键是要耐下心好好模拟。

具体代码如下:

#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
//SHCD
pii alice[10], bob[10], community[10];
int res[105];//alice手牌状态为i时的结果
bool vis[10];
unordered_map<char, int> mp;

bool cmp(pii x, pii y){
	return x.first > y.first;
}

void input(pii &p){
	string s;
	cin >> s;
	p.first = mp[s[0]];
	p.second = mp[s[1]];
}

int check(pii a[]){
	int hand;
	bool flush = false, straight = true, special = false;
	sort(a+1, a+6, cmp);
	int suit[10] = {0};
	int rank[20] = {0};
	for(int i = 1; i <= 5; i++){
		suit[a[i].second]++;
		rank[a[i].first]++;
		if(suit[a[i].second] == 5) flush = true;
		if(i < 5 && a[i].first-a[i+1].first != 1) straight = false;
	}
	if(rank[14] && rank[2] && rank[3] && rank[4] && rank[5]){
		straight = true;
		special = true;
	}
	int num[5] = {0};
	vector<int> vec[5];
	for(int i = 2; i <= 14; i++){
		num[rank[i]]++;
		vec[rank[i]].push_back(i);
	}
	//Royal flush
	if(flush && rank[10] && rank[11] && rank[12] && rank[13] && rank[14])
		hand = 10;
	//Straight flush
	else if(flush && straight){
		if(special)
			a[1].first = 5, a[2].first = 4, a[3].first = 3, a[4].first = 2, a[5].first = 1;
		hand = 9;
	}
	//Four of a kind
	else if(num[4]){
		for(int i = 1; i <= 4; i++)
			a[i].first = vec[4][0];
		a[5].first = vec[1][0];
		hand = 8;
	}
	//Full house
	else if(num[3] && num[2]){
		for(int i = 1; i <= 3; i++)
			a[i].first = vec[3][0];
		for(int i = 4; i <= 5; i++)
			a[i].first = vec[2][0];
		hand = 7;
	}
	//Flush
	else if(flush)
		hand = 6;
	//Straight
	else if(straight){
		if(special)
			a[1].first = 5, a[2].first = 4, a[3].first = 3, a[4].first = 2, a[5].first = 1;
		hand = 5;
	}
	//Three of a kind
	else if(num[3]){
		for(int i = 1; i <= 3; i++)
			a[i].first = vec[3][0];
		a[4].first = vec[1][0];
		a[5].first = vec[1][1];
		if(a[4].first < a[5].first)
			swap(a[4], a[5]);
		hand = 4;
	}
	//Two pairs
	else if(num[2] == 2){
		int t1 = vec[2][0], t2 = vec[2][1];
		if(t1 < t2) swap(t1, t2);
		a[1].first = a[2].first = t1;
		a[3].first = a[4].first = t2;
		a[5].first = vec[1][0];
		hand = 3;
	}
	//Pair
	else if(num[2]){
		for(int i = 1; i <= 2; i++)
			a[i].first = vec[2][0];
		int t1 = vec[1][0], t2 = vec[1][1], t3 = vec[1][2];
		if(t1 > t2) swap(t1, t2);
		if(t2 > t3) swap(t2, t3);
		if(t1 > t2) swap(t1, t2);
		a[3].first = t3;
		a[4].first = t2;
		a[5].first = t1;
		hand = 2;
	}
	//Highcard
	else
	 	hand = 1;
	return hand;
}

int dfs(int a, int step){//a表示alice手牌状态
	if(step == 7) return res[a];
	int num[4] = {0};//记录子状态中各结果出现次数
	for(int i = 0; i < 6; i++){
		if(vis[i]) continue;
		vis[i] = true;
		if(step&1) num[dfs(a|(1<<i), step+1)]++;
		else num[dfs(a, step+1)]++;
		vis[i] = false;
	}
	if(step&1){
		if(num[1]) return 1;
		else if(num[3]) return 3;
		else return 2;
	}
	else{
		if(num[2]) return 2;
		else if(num[3]) return 3;
		return 1;
	}
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	mp['2'] = 2;
	mp['3'] = 3;
	mp['4'] = 4;
	mp['5'] = 5;
	mp['6'] = 6;
	mp['7'] = 7;
	mp['8'] = 8;
	mp['9'] = 9;
	mp['T'] = 10;
	mp['J'] = 11;
	mp['Q'] = 12;
	mp['K'] = 13;
	mp['A'] = 14;
	mp['S'] = 1;
	mp['H'] = 2;
	mp['C'] = 3;
	mp['D'] = 4;
	int T;
	cin >> T;
	while(T--){
		memset(res, 0, sizeof res);
		memset(vis, false, sizeof vis);
		pii cpy_alice[3], cpy_bob[3];
		input(alice[1]);
		cpy_alice[1] = alice[1];
		input(alice[2]);
		cpy_alice[2] = alice[2];
		input(bob[1]);
		cpy_bob[1] = bob[1];
		input(bob[2]);
		cpy_bob[2] = bob[2];
		for(int i = 1; i <= 6; i++)
			input(community[i]);
		for(int i = 0; i < 1<<6; i++){
			int cnt = 0;
			for(int j = 0; j < 6; j++)
				if(i&(1<<j)) cnt++;
			if(cnt == 3){
				alice[1] = cpy_alice[1], alice[2] = cpy_alice[2];
				bob[1] = cpy_bob[1], bob[2] = cpy_bob[2];
				int num1 = 2, num2 = 2;
				for(int j = 0; j < 6; j++)
					if(i&(1<<j)) alice[++num1] = community[j+1];
					else bob[++num2] = community[j+1];
				int a_hand = check(alice);
				int b_hand = check(bob);
				if(a_hand > b_hand) res[i] = 1;//alice win
				else if(a_hand < b_hand) res[i] = 2;//bob win
				else{
					vector<int> a, b;
					for(int i = 1; i <= 5; i++){
						a.push_back(alice[i].first);
						b.push_back(bob[i].first);
					}
					if(a > b) res[i] = 1;
					else if(a < b) res[i] = 2;
					else res[i] = 3;//draw
				}
			}
		}
		int ans = dfs(0, 1);
		if(ans == 1) cout << "Alice" << endl;
		else if(ans == 2) cout << "Bob" << endl;
		else cout << "Draw" << endl;
	}
	return 0; 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值