UVa 1637 - Double Patience(概率DP)

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4512

 

题意:

36张牌分成9堆,每堆4张牌。每次可以拿走某两堆顶部的牌,但需要点数相同。如果有多种拿法则等概率的随机拿。
例如,9堆顶部的牌分别为KS, KH, KD, 9H, 8S, 8D, 7C, 7D, 6H,
则有5种拿法(KS,KH), (KS,KD), (KH,KD), (8S,8D), (7C,7D),每种拿法的概率均为1/5。
如果最后拿完所有牌则游戏成功。按顺序给出每堆牌的4张牌,求成功概率。

 

分析:

用9元组表示当前状态,即每堆牌剩的张数,状态总数为5^9=1953125。
设d[i]表示状态i对应的成功概率,则根据全概率公式,d[i]为后继状态的成功概率的平均值。

 

代码:

 1 import java.io.*;
 2 import java.util.*;
 3 
 4 public class Main {
 5     static char card[][][] = new char[9][4][2+5];
 6     static HashMap<ArrayList<Integer>,Double> d
 7             = new HashMap<ArrayList<Integer>,Double>();
 8     
 9     static double dp(ArrayList<Integer> A, int c) { // c为剩余总牌数
10         if(c == 0) return 1;
11         if(d.containsKey(A)) return d.get(A);
12         int tot = 0;
13         double sum = 0;
14         for(int t = 0; t < 9; t++) if(A.get(t) > 0) {
15             for(int i = t+1; i < 9; i++) if(A.get(i) > 0) {
16                 if(card[t][A.get(t)-1][0] != card[i][A.get(i)-1][0]) continue;
17                 tot++;
18                 A.set(t, A.get(t)-1);  A.set(i, A.get(i)-1);
19                 sum += dp(A, c-2);
20                 A.set(t, A.get(t)+1);  A.set(i, A.get(i)+1);
21             }
22         }
23         d.put(A, tot == 0 ? 0.0 : sum / tot);
24         return d.get(A);
25     }
26     
27     public static void main(String args[]) {
28         Scanner cin = new Scanner(new BufferedInputStream(System.in));
29         
30         while(cin.hasNext()) {
31             for(int r = 0; r < 9; r++)
32                 for(int c = 0; c < 4; c++)
33                     card[r][c] = cin.next().toCharArray();
34             d.clear();
35             ArrayList<Integer> A = new ArrayList<Integer>();
36             for(int i = 0; i < 9; i++) A.add(4);
37             System.out.printf("%.6f\n", dp(A, 36));
38         }
39         cin.close();
40     }
41 }

 

转载于:https://www.cnblogs.com/hkxy125/p/8934603.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值