UVa 1637 Double Patience (概率DP)

Posted forth

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 1637 Double Patience (概率DP)相关的知识,希望对你有一定的参考价值。

题目

题目大意

(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
", 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)的主要内容,如果未能解决你的问题,请参考以下文章

[UVa1637]Double Patience

UVA1637Double Patience(概率 + 记忆化搜索)

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

UVA 127 "Accordian" Patience

UVa127 "Accordian" Patience (模拟)

习题 6-9 UVA - 127"Accordian" Patience