UVa 1637 Double Patience (搜索)

本文介绍了一种通过深度优先搜索算法解决牌堆游戏的成功概率计算问题。游戏中36张牌被分为9堆,每堆4张,玩家需依次取走点数相同的两张牌直至牌堆为空。文章详细阐述了使用九元组状态表示法和动态规划来计算最终成功概率的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:36张牌分成9堆,每堆4张牌。每次可以拿走某两堆顶部的牌,但需要点数相同。如果有多种拿法则等概率的随机拿。例如,9堆顶部的牌分别为KS,KH,KD,9H, 8S,8D,7C,7D,6H,则有5种拿法(KS,KH),(KS,KD),(KH,KD),(8S,8D),(7C,7D),每种拿法的概率均为1/5.如果最后拿完所有的牌则游戏成功。按顺序给出每堆牌的4张牌,求成功的概率。

思路:用9元组表示当前的状态,即每堆的剩余牌数,dp[][][][][][][][][]表示可以这么那,则为1,概率为 (dp和)/个数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn = 5;
double dp[maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn];
int top[10];
bool vis[maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn];
vector<char> v[10];

double dfs(int t1, int t2, int t3, int t4, int t5, int t6, int t7, int t8, int t9) {
	bool &vvis = vis[t1][t2][t3][t4][t5][t6][t7][t8][t9];
	double &x = dp[t1][t2][t3][t4][t5][t6][t7][t8][t9];
	if(vvis) return x;
	vvis = true;
	int top[10] = {t1,t2,t3,t4,t5,t6,t7,t8,t9};
	bool flag = false;
	for(int i = 0; i < 9; ++i) {
		if(top[i]) flag = true;
	}
	if(!flag) return x = 1.0;
	int Count = 0;
	for(int i = 0; i < 8; ++i) {
		if(top[i])
		for(int j = i+1; j < 9; ++j) {
			if(top[j] && v[i][top[i]-1] == v[j][top[j]-1]) {
				Count++;
				top[i]--; top[j]--;
				x += dfs(top[0], top[1], top[2], top[3], top[4], top[5], top[6], top[7], top[8]);
				top[i]++; top[j]++;
			}
		}
	}
	if(x == 0) return x = 0;
	else return x = x*1.0/(Count*1.0);
}

int main() {
	char s0[2], s1[2], s2[2], s3[2];
	while(~scanf("%s%s%s%s", s0, s1, s2, s3)) {
		v[0].push_back(s0[0]);
		v[0].push_back(s1[0]);
		v[0].push_back(s2[0]);
		v[0].push_back(s3[0]);
		for(int i = 1; i < 9; ++i) {
			scanf("%s%s%s%s", s0, s1, s2, s3);
			v[i].push_back(s0[0]);
			v[i].push_back(s1[0]);
			v[i].push_back(s2[0]);
			v[i].push_back(s3[0]);
		}
		printf("%.6lf\n", dfs(4,4,4,4,4,4,4,4,4));
		memset(dp, 0, sizeof(dp));
		memset(vis, false, sizeof(vis));
		for(int i = 0; i < 9; ++i) v[i].clear();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JalexDooo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值