欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-31 16:35:58
写代码一定要注意!!!!!! 我因为i+1写成了1+1改了一晚上!!!!!!(菜都写脸上了) 题目: Double Patience是一种单人游戏,使用标准的36张牌组。这些牌在洗牌后放在一张桌子上,叠成9叠,每叠4张,面朝上。 牌放下后,玩家转身。每一次,他可以从任意两个牌堆中取出同一等级的*牌 ......

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

我因为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 }

就这样吧

上一篇:

下一篇: