1 条题解
-
0
问题理解
在二十一点(Blackjack)游戏中,玩家和庄家最初各发两张牌。庄家的一张牌是明牌(玩家可以看到),另一张牌是暗牌(玩家看不到)。给定玩家手中的两张初始牌和庄家的明牌,要求计算玩家手中的两张牌比庄家的两张牌更优的概率。这个问题的核心在于计算在初始发牌时,玩家牌点数优于庄家牌点数的概率。
解决思路
牌的点数计算: A(Ace)的点数可以是 1 或 11(由持牌人选择)。 K、Q、J 的点数为 10。 其余牌的点数为其面值。 玩家和庄家的牌点数: 玩家有两张牌,计算其点数和。 庄家有一张明牌,暗牌的点数未知,因此需要计算庄家所有可能的牌点数组合。 概率计算: 计算庄家可能的牌点数组合,并统计其中小于玩家牌点数的组合数量。 根据牌堆中剩余的牌计算概率。 多副牌处理: 使用多副牌时,牌堆中每种牌的数量为 4×n。 代码实现 以下是代码的详细实现:
#include <iostream> #include <cstring> #include <cstdio> // 添加这个头文件以使用 printf using namespace std; // 计算牌的点数 int ret(char a) { if (a == 'A') return 11; if (a == 'T' || a == 'J' || a == 'Q' || a == 'K') return 10; return a - '0'; } // 将牌转换为数值,用于索引 int gt(char a) { if (a == 'A') return 14; if (a == 'K') return 13; if (a == 'Q') return 12; if (a == 'J') return 11; if (a == 'T') return 10; return a - '0'; } int main() { int card, left, i; char lock[20], a, b, c; while (cin >> card && card) { memset(lock, 0, sizeof(lock)); cin >> c >> a >> b; int sum = 0, soc = 0, w = 0; // 计算玩家的牌点数 if (a == 'A' && b == 'A') sum = 12; // 两个 A 的特殊情况 else { sum += ret(a); sum += ret(b); } // 计算庄家明牌的点数 soc = ret(c); // 标记庄家暗牌可能的点数,使得庄家总点数小于玩家 for (i = 2; i <= 9; i++) if (soc + i < sum) lock[i] = 1; if (soc + 10 < sum) for (i = 10; i <= 13; i++) lock[i] = 1; if (soc <= 10 && soc + 11 < sum) lock[14] = 1; else if (soc > 10 && soc + 1 < sum) lock[14] = 1; // 计算剩余的牌数 left = 52 * card - 3; // 计算符合条件的牌数 for (i = 2; i < 15; i++) if (lock[i]) w += 4 * card; // 减去已经使用的牌 if (lock[gt(a)]) w--; if (lock[gt(b)]) w--; if (lock[gt(c)]) w--; // 输出概率 printf("%.3lf%%\n\n", double(w) * 100.0 / double(left)); } return 0; }
代码解释
ret 函数: 用于计算单张牌的点数,考虑 A 的特殊情况。 gt 函数: 将牌转换为数值,用于索引和标记。 主函数: 读取输入,包括牌副数和牌信息。 计算玩家和庄家的牌点数。 标记庄家暗牌可能的点数,使得庄家总点数小于玩家。 计算剩余的牌数和符合条件的牌数。 输出概率,保留三位小数。 通过上述代码,我们可以计算出在初始发牌时,玩家牌点数优于庄家牌点数的概率。
- 1
信息
- ID
- 1006
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者