●POJ 2794 Double Patience

题链:

http://poj.org/problem?id=2794
题解:

状压DP,概率
9元组表示每一堆还剩几张牌。可以用5进制状压,共5^9=1953124个状态。
令P(S)表示S这个状态被取完的概率。

假设当前状态为S,可以有三种取法,分别对应转移到_S1,_S2,_S3三个更小的状态。
那么由全概率公式:
如果_S1状态为前提条件,那么S就有1/3的概率转移到_S1
同理_S2,_S3。所以得出:
P(S)=P(S|_S1)*P(_S1)+P(S|_S2)*P(_S2)+P(S|_S3)*P(_S3)
由于P(S|_S1=)P(S|_S2)=P(S|_S3)=1/3
所以P(S)=(P(_S1)+P(_S2)+P(_S3))/3

即每个状态的概率为其后继状态的平均值。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char card[10][5];
bool vis[2000000];
double dp[2000000];
int code(int *a){
	static int s; s=0;
	for(int i=9;i>=1;i--)
		s=s*5+a[i];
	return s;
}
void decode(int s,int *a){
	for(int i=1;i<=9;i++)
		a[i]=s%5,s/=5;
}
double DP(int s){
	if(vis[s]) return dp[s];
	vis[s]=1;
	int a[10],cnt=0; decode(s,a);
	for(int i=1;i<=9;i++)
		for(int j=i+1;j<=9;j++){
			if(!a[i]||!a[j]||card[i][a[i]]!=card[j][a[j]]) continue;
			a[i]--; a[j]--; cnt++;
			int _s=code(a);
			dp[s]+=DP(_s);
			a[i]++; a[j]++;
		}
	if(cnt) dp[s]/=cnt;
	return dp[s];
}
int main(){
	static char S[5];
	for(int i=1;i<=9;i++)
		for(int j=1;j<=4;j++)
			scanf("%s",S),card[i][j]=S[0];
	vis[0]=1; dp[0]=1;
	printf("%.6lf\n",DP(1953124));
	return 0;
}

  

原文地址:https://www.cnblogs.com/zj75211/p/8541926.html

时间: 2024-10-12 15:37:46

●POJ 2794 Double Patience的相关文章

UVA 1637 Double Patience 概率DP

Double Patience Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Double Patience is a single player game played with a standard 36-card deck. The cards are shuffled and laid down on a table in 9 pile

Uva 127 poj 1214 `Accordian&#39;&#39; Patience

 ``Accordian'' Patience  You are to simulate the playing of games of ``Accordian'' patience, the rules for which are as follows: Deal cards one by one in a row from left to right, not overlapping. Whenever the card matches its immediate neighbour on

1637 - Double Patience(状态转移+求成功概率)

用九元组表示当前状态,即每队牌剩的张数,状态总数为5^9=1953125. 设d[ i ]表示状态i对应的成功概率,则根据全概率公式,d[ i ]为后继成功概率的平均值,按照动态规划的写法计算即可. 这个动态规划我不会写,帅哥思路真的很清晰很好啊. 但是学会还是很高兴的 #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #d

[Uva1637][DFS][记忆化] 纸牌游戏 Double Patience

写代码一定要注意!!!!!! 我因为i+1写成了1+1改了一晚上!!!!!!(菜都写脸上了) 题目: Double Patience是一种单人游戏,使用标准的36张牌组.这些牌在洗牌后放在一张桌子上,叠成9叠,每叠4张,面朝上. 牌放下后,玩家转身.每一次,他可以从任意两个牌堆中取出同一等级的顶级牌,然后将它们移除.如果有几种可能性,玩家可以选择任何一种.如果所有的牌都从桌上移除,玩家将赢得游戏,如果一些牌仍然在桌上,并且没有有效的移动,玩家将失败. 乔治喜欢这种游戏.但当有几种可能时,他不知道

AVL树(模板题)—— POJ 3481 Double Queue

对应POJ题目:点击打开链接 Double Queue Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11741   Accepted: 5335 Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped with a modern computing env

poj 3841 Double Queue (AVL树入门)

1 /****************************************************************** 2 题目: Double Queue(poj 3481) 3 链接: http://poj.org/problem?id=3481 4 算法: avl树(入门) 5 *******************************************************************/ 6 #include<cstdio> 7 #inclu

POJ 3481 Double Queue(Treap模板题)

Double Queue Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15786   Accepted: 6998 Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped with a modern computing environment provid

跳跃表基础——POJ 3481 Double Queue

对应POJ 题目:点击打开链接 Double Queue Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11768   Accepted: 5349 Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped with a modern computing en

1637 - Double Patience (概率DP)

一道状态较多的概率DP,想要表示所有的状态显然要拓展几个维度表示九堆牌当前的状态 . 但是这么写太复杂,所以我们不妨用一个vector来储存状态,将dp数组用一个map来表示,即 map<vector<int> ,double> d; 利用vector可以作为函数参数传递这个优点,将大大节省代码量 . 概率很好求,在每一次迭代中,寻找所有可以转移的状态数tot,那么状态转移就是d[i] = sum(d[i-1])/tot . 也就是全概率公式 . 递归边界是当所有牌都被摸走了,返回