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

写代码一定要注意!!!!!!

我因为i+1写成了1+1改了一晚上!!!!!!(菜都写脸上了)

题目:

Double Patience是一种单人游戏,使用标准的36张牌组。这些牌在洗牌后放在一张桌子上,叠成9叠,每叠4张,面朝上。

牌放下后,玩家转身。每一次,他可以从任意两个牌堆中取出同一等级的顶级牌,然后将它们移除。如果有几种可能性,玩家可以选择任何一种。如果所有的牌都从桌上移除,玩家将赢得游戏,如果一些牌仍然在桌上,并且没有有效的移动,玩家将失败。

乔治喜欢这种游戏。但当有几种可能时,他不知道要选择哪一张。乔治不想多想,所以在这种情况下,他只需从可能的情况中选择一对随机的,并删除它。乔治选择每种情况的可能性相同。

例如,如果最上面的牌是Ks、Kh、Kd、9h、8s、8d、7c、7d和6h,他会删除任何一对在(KS, KH)、(KS, KD)、(KH, KD)、 (8S, 8D)和 (7C, 7D)中的任何一对。删除(Ks,Kh)、(Ks,Kd)、(Kh,Kd)、(8s,8d)和(7c,7d)的概率都为1/5。

请算出在游戏开始时,根据桌上的牌,找出如果乔治按照描述行事,他赢得游戏的可能.

大概意思就是说有 9 堆牌, 每堆 4 张, 当两堆当前最顶上纸牌相同时可以拿走, 问只要有可以拿走的纸牌就拿走, 最后能够拿完纸牌的概率有多大

这题乍一看除了搜索并没有什么思路显然是搜索题嘛

可以直接优雅简单粗暴的开一个九维(确信)数组

ans[5][5][5][5][5][5][5][5][5]

记录一下每一种情况下的胜率

这样我们可以知道:

当牌拿完时获胜, 即 ans[0][0][0][0][0][0][0][0][0] = 1;

然后就可以写循环暴力枚举每一种情况了.

每找到一种拿牌方案, 这一层搜索的总方案数+1;

这一层搜索的胜率就是 (所有找到的方案的胜率之和) / (所有找到的方案数)

找不到方案时胜率显然是0;

然后你就会发现TLE了

所以这题需要用到记忆化

一个方案如果被搜过了, 就直接返回胜率而不向下枚举

所以再开一个bool数组记录访问状态

那么边界就是没有牌的状态是访问过的(即直接返回ans[0][0][0][0][0][0][0][0][0] = 1)

这题就AC了

下面是代码

这题代码相当不优雅

 1 /*
 2 思路:DFS
 3 开两个九维(确信)数组,一个double型,用来记录每一堆每一层纸牌的胜率
 4 当然可以暴搜,但是会TLE,所以第二个bool类型的数组便派上用场了:记忆化
 5 bool类型这个数组记录一个情况有没有经历过
 6 每一种情况的胜率:从这一种情况开始搜的胜率之和除以所有搜到的情况之和
 7 当搜到一层无法再次往下搜索时该状态胜率为0
 8 当纸牌能被搜完时胜率为1
 9 花色对结果不造成影响
10 */
11
12 # include <cstdio>
13 # include <iostream>
14
15 using namespace std;
16
17 int poker[10][5]; // 九堆纸牌一堆四个
18 double ans[5][5][5][5][5][5][5][5][5];
19 bool vis[5][5][5][5][5][5][5][5][5];
20
21 double dfs(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8, int h9){
22     if(vis[h1][h2][h3][h4][h5][h6][h7][h8][h9])
23         return ans[h1][h2][h3][h4][h5][h6][h7][h8][h9];
24     vis[h1][h2][h3][h4][h5][h6][h7][h8][h9] = true; // 记忆化
25
26     int height[20] = {0, h1, h2, h3, h4, h5, h6, h7, h8, h9}; // 记录每堆纸牌高度
27
28     double sumRate = 0.0; // 记录胜率
29     double sumSol = 0; // 记录找到的取牌方法总数
30
31     for(int i = 1; i <= 9; i++){
32         for(int j = i + 1; j <= 9; j++){
33             if(height[i] > 0 && height[j] > 0 && poker[i][height[i]] == poker[j][height[j]]){
34                 height[i] -= 1;
35                 height[j] -= 1;
36                 sumSol += 1;
37                 // if(height[1]>=0&&height[2]>=0&&height[3]>=0&&height[4]>=0&&height[5]>=0&&height[6]>=0&&height[7]>=0&&height[8]>=0&&height[9]>=0)
38                 sumRate += dfs(height[1], height[2], height[3], height[4], height[5], height[6], height[7], height[8], height[9]);
39                 height[i]++;
40                 height[j]++;
41             }
42         }
43     }
44
45     if(sumSol > 0) return ans[h1][h2][h3][h4][h5][h6][h7][h8][h9] = sumRate / sumSol;
46     else return ans[h1][h2][h3][h4][h5][h6][h7][h8][h9];
47 }
48
49 int main(){
50     vis[0][0][0][0][0][0][0][0][0] = 1;
51     ans[0][0][0][0][0][0][0][0][0] = 1.00;
52     char p1[3], p2[3], p3[3], p4[3];
53     for(int i = 1; i <= 9; i++){
54         cin>>p1>>p2>>p3>>p4;
55         poker[i][1] = p1[0] - ‘0‘;
56         poker[i][2] = p2[0] - ‘0‘;
57         poker[i][3] = p3[0] - ‘0‘;
58         poker[i][4] = p4[0] - ‘0‘;
59     }
60
61     printf("%.6lf", dfs(4, 4, 4, 4, 4, 4, 4, 4, 4));
62
63     return 0;
64 }

就这样吧

原文地址:https://www.cnblogs.com/Foggy-Forest/p/12425789.html

时间: 2024-08-09 16:43:11

[Uva1637][DFS][记忆化] 纸牌游戏 Double Patience的相关文章

How many ways(dfs+记忆化搜索)

Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 1.机器人一开始在棋盘的起始点并有起始点所标有的能量. 2.机器人只能向右或者向下走,并且每走一步消耗一单位能量. 3.机器人不能在原地停留. 4.当机器人选择了一条可行路径后,当他走到这条路径的终点时,他将只有终点所标记的能量. [center] [img]../../../data/images/C113-1003-1.gif[/img]

hdu 1501 Zipper (dfs+记忆化搜索)

Zipper Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6491    Accepted Submission(s): 2341 Problem Description Given three strings, you are to determine whether the third string can be formed

ZOJ 3644 Kitty&#39;s Game dfs,记忆化搜索,map映射 难度:2

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4834 从点1出发,假设现在在i,点数为sta,则下一步的点数必然不能是sta的因数,所以不会形成环,只需从1直接走,走到n即可. 但是如果这样的话时空复杂度就都是nk,明显不满足题意,而这个时候我们可以想到,每个状态都必然是k的约数,(点数不是k的约数的节点不在路上,可以无视),而约数的个数也就k^0.5个,可以直接用map映射,这样时空复杂度都是n*k^0.5,可以解出答案

HDU 5024 Wang Xifeng&#39;s Little Plot (枚举 + DFS记忆化搜索)

Wang Xifeng's Little Plot Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 513    Accepted Submission(s): 338 Problem Description <Dream of the Red Chamber>(also <The Story of the Stone>)

HDU 1484 Basic wall maze (dfs + 记忆化)

Basic wall maze Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 168    Accepted Submission(s): 52 Special Judge Problem Description In this problem you have to solve a very simple maze consisti

不要62 hdu 2089 dfs记忆化搜索

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意: 给你两个数作为一个闭区间的端点,求出该区间中不包含数字4和62的数的个数 思路: 数位dp中的 dfs 记忆化搜索方法解. 模板: int dfs(int i, int s, bool e) { if (i==-1) return s==target_s; if (!e && f[i][s] != -1) return f[i][s]; int res = 0; int u = e?

poj1088滑雪(dfs+记忆化搜索、备忘录)

题目信息: Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小.在上面的例子中,一条可滑

NYOJ skiing(DFS+记忆化搜索)

skiing 时间限制:3000 ms  |  内存限制:65535 KB 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点

poj1088-滑雪 【dfs 记忆化搜索】

http://poj.org/problem?id=1088 滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 79806   Accepted: 29701 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字