列表

详情


NC17191. 爆搜题

描述

德克萨斯扑克是一种风靡全球的游戏,下面将介绍它的规则。

它由52张标准牌组成(除去鬼牌),有4种花色(黑桃,红心,方片和梅花),13种不同类型的牌A、K、Q、J、2、3、4、5、6、7、8、9、10。

游戏由两名玩家进行。一开始每一名玩家抽两张牌并将面朝下,称为底牌。底牌将不会公示出来直到比较阶段。接着主持人将会在剩下的牌中再抽出三张当做公共牌,也就是说,这三张牌是两名玩家都有所有权的。

之后主持人会在剩下来的牌中,再抽出两张牌,一共组成5张双方玩家都可以使用的牌。主持人在确定公共牌之后,扑克游戏进行比较环节。每个玩家展示自己的底牌,并且从7张牌(自己的底牌+5张公共牌)中选出5张来成为自己的手牌(注意:公共牌双方都可以使用,也就是说可以允许某张公共牌同时成为两名玩家的手牌),根据组出来的手牌的强度来决定胜负。

下面是10种可能的手牌类型,从强到弱排序如下:

对于组成顺子而言,J、Q、K可以分别被看做11、12、13。A既可以被看做14,也可以看做1,也就是说A、K、Q、J、10是一个合法的顺子,5、4、3、2、A也是一个合法的顺子,但是3、2、A、K、Q不是一个合法的顺子。

玩家各自从自己手牌中挑出最强的手牌类型组,如果两名玩家挑出来都是同类型的手牌类型,那么将对该类型的手牌类型进行比较。特别地,比较方法如下:

特别注意:牌的花色不影响牌面大小的比较。

对于牌面的大小,顺序从大到小依次是A,K,Q,J,10,9,…,2。当A在顺子中被视为1的时候,A的大小位置被视为比2更小。

下面来举出一些例子来方便进行理解。

在世纪之交的x000年,M国最高的人W来到了Mr. F的王国,并进行了一次高水平的采访。这次采访的剪辑录像后来被收入了Mr. F的经典视频资料集中。

采访之余,W提出想和Mr. F进行一场公平的对决,于是选定了德州扑克这一游戏。Mr. F无所不知,在底牌和前三张公共牌已经抽出的时候,他已经知道了W的两张底牌是什么,而剩下的两张牌将随机从牌组中抽出。(也就是说,Mr. F已经知道了双方的底牌和三张公共牌的类型和花色)

Mr. F希望知道剩下两张牌随机抽出的情况下,他和W赌上了国家荣誉全力以赴比赛的情况下,Mr. F获胜的概率有多大。Mr. F认为平局意味着W能达到他的水平,这是他不能容忍的,所以他认为平局不算获胜。

输入描述

本题有多组测试数据,测试数据以一个#结束。

对于一张牌,用两个字符构成: 第一个字符为S、H、D、C的一种,分别表示黑桃、红心、方片、梅花。第二个字符为A、K、Q、J、T,和2到9的一种, 其中T代表10。

对于每一组测试数据,由三行组成:

第一行有两个字符串,表示Mr. F的两张底牌。

第二行有两个字符串,表示W的两张底牌。

第三行有三个字符串,表示已抽出的三张牌。

输出描述

每组数据输出一个实数,表示Mr. F获胜的概率,四舍五入到小数点后3位。

示例1

输入:

SA SK
DA CA
SQ SJ ST
SA HA
D2 C3
H4 S5 DA
HA D9
H6 C9
H3 H4 H5
#

输出:

1.000
0.344
0.630

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 166ms, 内存消耗: 380K, 提交时间: 2018-07-13 20:33:17

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <numeric>
#define rank _rk
using namespace std;

const char *suit = "SHDC";
const char *rank = "A23456789TJQK";  // 0 to 12
const double eps = 1e-8;

bool c1[4][13], c2[4][13], c3[4][13], c[4][13];

pair<int, int> Read(void) {
  char s[3];
  scanf("%s", s);
  if (s[0] == '#') exit(0);
  int b = strchr(suit, s[0]) - suit;
  int a = strchr(rank, s[1]) - rank;
  return {b, a};
}

void Set(bool c[4][13]) {
  pair<int, int> a = Read();
  c[a.first][a.second] = 1;
}

int Hash(const int *a) {
  int h = 0;
  vector< pair<int, int> > b;
  for (int i = 13; i > 0; --i) {
    for (int j = 0; j < a[i % 13]; ++j) {
      b.push_back({a[i % 13], i});
    }
  }
  sort(b.begin(), b.end());
  reverse(b.begin(), b.end());
  for (auto p : b) {
    int j = p.second;
    h = h * 13 + j - 1;
  }
  return h;
}

pair<int, int> Score_(void) {
  int a[13] = {};
  for (int i = 0; i < 4; ++i) {
    for (int j = 0; j < 13; ++j) {
      a[j] += c[i][j];
    }
  }
  if (accumulate(a, a + 13, 0) != 5) throw;

  // tong hua shun
  for (int i = 0; i < 4; ++i) {
    for (int j = 0; j < 10; ++j) {
      bool good = true;
      for (int k = 0; k < 5; ++k) if (!c[i][(j + k) % 13]) good = false;
      if (good) return {10, j};
    }
  }

  // si tiao
  if (count(a, a + 13, 4) == 1) {
    return {9, Hash(a)};
  }

  // man tang hong
  if (count(a, a + 13, 3) == 1 && count(a, a + 13, 2) == 1) {
    return {8, Hash(a)};
  }

  // tong hua
  for (int i = 0; i < 4; ++i) {
    if (count(c[i], c[i] + 13, true) == 5) {
      return {7, Hash(a)};
    }
  }

  // shun zi
  for (int j = 0; j < 10; ++j) {
    bool good = true;
    for (int k = 0; k < 5; ++k) if (!a[(j + k) % 13]) good = false;
    if (good) return {6, j};
  }

  // san tiao
  if (count(a, a + 13, 3) == 1) {
    return {5, Hash(a)};
  }

  // shaung dui
  if (count(a, a + 13, 2) == 2) {
    return {4, Hash(a)};
  }

  // dui zi
  if (count(a, a + 13, 2) == 1) {
    return {3, Hash(a)};
  }

  // gao pai
  return {2, Hash(a)};
}

pair<int, int> Score(const vector< pair<int, int> > &card) {
  pair<int, int> ans = {0, 0};
  for (int s = 0; s < 1 << 7; ++s) {
    if (__builtin_popcount(s) == 5) {
      memset(c, 0, sizeof c);
      for (int i = 0; i < 7; ++i) {
        if (s >> i & 1) {
          c[card[i].first][card[i].second] = true;
        }
      }
      ans = max(ans, Score_());
    }
  }
  return ans;
}

bool Solve(int a1, int b1, int a2, int b2) {
  vector< pair<int, int> > card;
  for (int i = 0; i < 4; ++i) {
    for (int j = 0; j < 13; ++j) {
      if (c1[i][j] || c3[i][j] ||
          (i == a1 && j == b1) || (i == a2 && j == b2)) {
        card.push_back({i, j});
      }
    }
  }
  if (card.size() != 7) throw;
  pair<int, int> p1 = Score(card);

  card.clear();
  for (int i = 0; i < 4; ++i) {
    for (int j = 0; j < 13; ++j) {
      if (c2[i][j] || c3[i][j] ||
          (i == a1 && j == b1) || (i == a2 && j == b2)) {
        card.push_back({i, j});
      }
    }
  }
  if (card.size() != 7) throw;
  pair<int, int> p2 = Score(card);
  return p1 > p2;
}

int main(void) {
  while (true) {
    memset(c1, 0, sizeof c1);
    memset(c2, 0, sizeof c2);
    memset(c3, 0, sizeof c3);
    Set(c1); Set(c1);
    Set(c2); Set(c2);
    Set(c3); Set(c3); Set(c3);
    int win = 0, tot = 0;
    for (int i = 0; i < 52; ++i) {
      for (int j = i + 1; j < 52; ++j) {
        int a1 = i % 4, b1 = i / 4;
        int a2 = j % 4, b2 = j / 4;
        if (c1[a1][b1] || c1[a2][b2] || c2[a1][b1] || c2[a2][b2] ||
            c3[a1][b1] || c3[a2][b2]) continue;
        win += Solve(a1, b1, a2, b2);
        tot += 1;
      }
    }
    char s1[10], s2[10];
    sprintf(s1, "%.3lf", (double)win / tot + eps);
    sprintf(s2, "%.3lf", (double)win / tot - eps);
    // if (strcmp(s1, s2)) while(1);
    puts(s1);
  }
  return 0;
}

上一题