[Uva1637][DFS][記憶化] 紙牌遊戲 Double Patience

寫代碼必定要注意!!!!!!

我由於i+1寫成了1+1改了一夜!!!!!!(菜都寫臉上了)

題目:ios

Double Patience是一種單人遊戲,使用標準的36張牌組。這些牌在洗牌後放在一張桌子上,疊成9疊,每疊4張,面朝上。數組

牌放下後,玩家轉身。每一次,他能夠從任意兩個牌堆中取出同一等級的頂級牌,而後將它們移除。若是有幾種可能性,玩家能夠選擇任何一種。若是全部的牌都從桌上移除,玩家將贏得遊戲,若是一些牌仍然在桌上,而且沒有有效的移動,玩家將失敗。spa

喬治喜歡這種遊戲。但當有幾種可能時,他不知道要選擇哪一張。喬治不想多想,因此在這種狀況下,他只需從可能的狀況中選擇一對隨機的,並刪除它。喬治選擇每種狀況的可能性相同。code

例如,若是最上面的牌是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。blog

請算出在遊戲開始時,根據桌上的牌,找出若是喬治按照描述行事,他贏得遊戲的可能.遊戲

 

大概意思就是說有 9 堆牌, 每堆 4 張, 當兩堆當前最頂上紙牌相同時能夠拿走, 問只要有能夠拿走的紙牌就拿走, 最後可以拿完紙牌的機率有多大ci

這題乍一看除了搜索並無什麼思路顯然是搜索題嘛io

能夠直接優雅簡單粗暴的開一個九維(確信)數組 class

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

記錄一下每一種狀況下的勝率stream

這樣咱們能夠知道:

當牌拿完時獲勝, 即 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 }

就這樣吧

相關文章
相關標籤/搜索