1. 程式人生 > >UVa 1637 Double Patience (概率DP)

UVa 1637 Double Patience (概率DP)

gis tab span 記憶化搜索 code 記憶化 rac print ble

題目

題目大意

\(36\)張牌分成\(9\)堆, 每堆\(4\)張牌。每次可以拿走某兩堆頂部的牌, 但需要點數相同。如果有多種拿法則等概率的隨機拿。例如, \(9\)堆頂部的牌分別為KS, KH, KD, 9H, 8S, 7C, 7D, 6H, 則有\(5\)種拿法(KS, KH), (KS, KD), (KH, KD), (8S, 8D), (7C, 7D), 每種拿法的概率均為\(\frac{1}{5}\)。如果最後拿完所有牌則遊戲成功。按順序給出每堆牌的\(4\)張牌, 求成功概率。

題解

記憶化搜索每一種情況, 使用一個std::map<std::vector<int> >

記錄情況。

代碼

#include <map>
#include <cstdio>
#include <vector>
std::map<std::vector<int>, double> hash_table;
char card[9][4][7];
inline double DepthFirstSearch(register std::vector<int>&, const int&);
int main(int argc, char const *argv[]) {
  while (~scanf("%s", card[0][0])) {
    for (register int c(1); c < 4; ++c) scanf("%s", card[0][c]);
    for (register int r(1); r < 9; ++r) {
      for (register int c(0); c < 4; ++c) {
        scanf("%s", card[r][c]);
      }
    }
    hash_table.clear();
    register std::vector<int> status(9, 4);
    printf("%.6lf\n", DepthFirstSearch(status, 36));
  }
}
inline double DepthFirstSearch(register std::vector<int> &status, const int &c) {
  if (!c) return 1.0;
  if (hash_table.count(status)) return hash_table[status];
  register int total(0);
  register double sum(0);
  for (register int t(0); t < 9; ++t) if(status[t] > 0){
    for (register int i(t + 1); i < 9; ++i) if (status[i] > 0) {
      if (card[t][status[t] - 1][0] != card[i][status[i] - 1][0]) continue;
      ++total,
      --status[t],
      --status[i],
      sum += DepthFirstSearch(status, c - 2),
      ++status[t],
      ++status[i];
    }
  }
  hash_table[status] = total ? sum / double(total) : 0.0;
  return hash_table[status];
}

UVa 1637 Double Patience (概率DP)