UVA1637Double Patience(概率 + 记忆化搜索)

训练指南P327

题意:36张牌分成9堆, 每堆4张牌。每次拿走某两堆顶部的牌,但需要点数相同。如果出现多种拿法则等概率的随机拿。 如果最后拿完所有的牌则游戏成功,求成功的概率。

开个9维数组表示每一堆的状态,模拟搜索一下

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 const int Max = 6;
 7 char s[Max][Max];
 8 int A[10][Max * Max];
 9 int vis[Max][Max][Max][Max][Max][Max][Max][Max][Max];
10 double d[Max][Max][Max][Max][Max][Max][Max][Max][Max];
11 double dfs(int s1, int s2, int s3, int s4, int s5, int s6, int s7, int s8, int s9)
12 {
13     if (vis[s1][s2][s3][s4][s5][s6][s7][s8][s9])
14         return d[s1][s2][s3][s4][s5][s6][s7][s8][s9];
15     vis[s1][s2][s3][s4][s5][s6][s7][s8][s9] = 1;
16     int T[10] = {0, s1, s2, s3, s4, s5, s6, s7, s8, s9};
17     bool flag = true;
18     for (int i = 1; i <= 9; i++)
19     {
20         if (T[i])
21         {
22             flag = false;
23             break;
24         }
25     }//如果全是0,表示结束,这个状态为1
26     if (flag)
27     {
28         return d[s1][s2][s3][s4][s5][s6][s7][s8][s9] = 1.0;
29     }
30     int tot = 0;
31     double cnt = 0;
32     for (int i = 1; i <= 9; i++)
33     {
34         for (int j = i + 1; j <= 9; j++)
35         {
36             if (T[i] > 0 && T[j] > 0 && A[i][ T[i] ] == A[j][ T[j] ])
37             {
38                 T[i]--;
39                 T[j]--;
40                 tot++; // 当前有几种选择方案
41                 cnt += dfs(T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]); // 选择 i 堆 和 j 堆之后剩下的全部取光的概率
42                 T[i]++;
43                 T[j]++;
44             }
45         }
46     }
47     if (tot > 0)
48         d[s1][s2][s3][s4][s5][s6][s7][s8][s9] = cnt / (1.0 * tot); //  (1 / tot ) * cnt;当前状态概率
49     return d[s1][s2][s3][s4][s5][s6][s7][s8][s9];
50 }
51 int main()
52 {
53     while (scanf("%s%s%s%s", s[1], s[2], s[3], s[4]) != EOF)
54     {
55         for (int i = 1; i <= 4; i++)
56             A[1][i] = s[i][0] - ‘0‘;  // A[i][j]用于记录第i堆第j个
57         for (int i = 2; i <= 9; i++)
58         {
59             for (int j = 1; j <= 4; j++)
60             {
61                 scanf("%s", s[j]);
62                 A[i][j] = s[j][0] - ‘0‘;
63             }
64         }
65         memset(vis, 0, sizeof(vis));
66         memset(d, 0, sizeof(d));
67         dfs(4, 4, 4, 4, 4, 4, 4, 4, 4);  // 所有的堆都是4个开始搜索
68         printf("%.6lf\n", d[4][4][4][4][4][4][4][4][4]);
69     }
70     return 0;
71 }

时间: 2024-10-19 03:44:09

UVA1637Double Patience(概率 + 记忆化搜索)的相关文章

Codeforces 540D Bad Luck Island - 概率+记忆化搜索

[题意] 一个岛上有三种生物A,B,C,各有多少只在输入中会告诉你,每种最多100只 A与B碰面,A会吃掉B, B与C碰面,B会吃掉C, C与A碰面,C会吃掉A...忍不住想吐槽这种环形食物链 碰面是随机的.到最后岛上只剩下一种生物,问这种生物分别是A,B,C的概率是多少. [题解] 其实很简单,这题,状态方程很好想.. 设dp[i][j][k]为生物A有i只,生物B有j只,生物C有k只的概率情况,显然dp的返回值应该有三个,分别是最后剩下该种生物的概率 那么我们考虑状态转移的情况. 如果A与B

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=

Codeforces 148D Bag of mice:概率dp 记忆化搜索

题目链接:http://codeforces.com/problemset/problem/148/D 题意: 一个袋子中有w只白老鼠,b只黑老鼠. 公主和龙轮流从袋子里随机抓一只老鼠出来,不放回,公主先拿. 公主每次抓一只出来.龙每次在抓一只出来之后,会随机有一只老鼠跳出来(被龙吓的了...). 先抓到白老鼠的人赢.若两人最后都没有抓到白老鼠,则龙赢. 问你公主赢的概率. 题解: 表示状态: dp[i][j] = probability to win(当前公主先手,公主赢的概率) i:剩i只白

HDU - 5001 Walk(概率dp+记忆化搜索)

Walk I used to think I could be anything, but now I know that I couldn't do anything. So I started traveling. The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel to an ad

多校5 1001 HDU5781 ATM Mechine 记忆化搜索+概率

1 // 多校5 1001 HDU5781 ATM Mechine 2 // http://acm.hdu.edu.cn/search.php?field=problem&key=2016+Multi-University+Training+Contest+5&source=1&searchmode=source 3 // 记忆化搜索 4 // 每次二分,决策最优,所以最多查询11次 5 // dp[i][j] 当前能确定i元情况下,还能被警告j次 6 // 下次取k,实际剩余t

【BZOJ1415】【Noi2005】聪聪和可可 概率DP 记忆化搜索

链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46457811"); } 题解: 记忆化搜索. f(i,j) 表示猫在 i .鼠在 j 时的期望. 然后显然它是拓扑的,然后先枚举起点n遍bfs算出 f(i,j) 时猫只走一步应该到哪个节点,然后对于 f(i,j) 枚

BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&amp;&amp;NOI2005全AC达成

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇 今天早上起床发现194了然后就各种刷--当我发现199的时候我决定把第200题交给05年NOI仅剩的一道题--结果尼玛调了能有一个小时--我居然没看到编号最小这个限制0.0 首先我们知道,由于聪聪走两步而可可走一步,所以聪聪一定能在有限的时刻追上可可,而且两人的距离随着时间进行单调递减 于是我们记忆化搜索 首先用

【BZOJ 1415】 1415: [Noi2005]聪聪和可可 (bfs+记忆化搜索+期望)

1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1640  Solved: 962 Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路. 所有的路都是无向的,即

HDU5001-Walk(记忆化搜索)

题目链接 题意:一张无向图,要你求出走d步之后,每个点无法到达的概率. 思路:记忆化搜索,枚举每个点a,dp[i][j]表示走了i步到达j点的概率(不包括a点),注意初始化清空. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int MAXN