链接:
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 }