UVa 1637 Double Patience (搜索)

題意: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();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章