Neerc2005 POJ2794 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张牌,求成功概率。


题目分析:(手动%aufeas。 用一个九维的数组f来表示这九堆剩余牌数时的概率大小。用记忆化搜索实现。每次枚举当前牌堆顶的牌,如果点数相等就累计一下。最后把这两张牌成功时的方案数/刚刚累计的方案数就是概率大小。累加起来。


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
#include<cassert>
#include<climits>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define INF (2139062143)
#define phiF (1000000006)
#define MAXN (1000000+10)
typedef long long LL;

double b[5][5][5][5][5][5][5][5][5],ans;
int a[10];
char c[10][5],s[5];
bool f[5][5][5][5][5][5][5][5][5];

double dfs(){
	double ans=0.0;
	int t=0,num=0,use[20];
	
	if (f[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]][a[8]]) {
		return b[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]][a[8]];
	}
	f[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]][a[8]]=1;
	
	Rep (i,9)
	if (a[i]) use[++t]=i;
	
	if (!t) return b[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]][a[8]]=1.0;
	For (i,t-1)
	 Fork (j,i+1,t)
	 if (c[use[i]][a[use[i]]]==c[use[j]][a[use[j]]]) num++;
	For (i,t-1)
	 Fork (j,i+1,t)
	 if (c[use[i]][a[use[i]]]==c[use[j]][a[use[j]]]) {
	 	a[use[i]]--;a[use[j]]--;
	 	ans+=dfs()/1.0/num;
	 	a[use[i]]++;a[use[j]]++;
	 }
	return 	b[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]][a[8]]=ans;
}



int main(){
	Rep (i,9){
	 For (j,4){
	    scanf("%s",s);
	    c[i][j]=s[0];
	 }
	 
	 scanf("\n");
	}
	Rep (i,9)a[i]=4;
	printf("%.10f",(double)dfs());
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值