You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于自定义骰子概率分布,计算100次投掷后登200级以上台阶的概率

计算100次掷骰子后到达200级以上台阶的概率

问题背景

初始位于楼梯底部(0级),掷骰子规则如下:

  • 掷出1或2:若不在底部则向下移动1级;若在底部则位置不变
  • 掷出3、4、5:向上移动1级
  • 掷出6:再次掷骰子,按第二次结果向上移动对应级数(第二次掷骰子同样使用给定的概率分布)

给定骰子6个面的概率分布(如[0.2,0.2,0.2,0.2,0.1,0.1]),需要计算100次投掷后,台阶数≥201的概率。

原代码的问题

你编写的rolldice函数存在两个关键问题:

  1. 第二次掷骰子(roll2)没有使用传入的概率分布D,而是用了默认的均匀分布,不符合问题要求
  2. 每次循环打印i, Stair会大幅降低模拟效率,不适合大规模重复运行

方法一:蒙特卡洛模拟(近似解)

通过重复运行模拟数千/数万次,统计最终台阶数≥201的次数占总次数的比例,得到近似概率。这是最直观的方法,适合快速得到结果。

优化后的模拟函数

import random

def rolldice(T: int, D):
    stair = 0
    for _ in range(T):
        roll1 = random.choices([1,2,3,4,5,6], weights=D)[0]
        if roll1 in (1, 2):
            if stair > 0:
                stair -= 1
        elif roll1 in (3,4,5):
            stair += 1
        elif roll1 == 6:
            # 第二次掷骰子同样使用给定的分布D
            roll2 = random.choices([1,2,3,4,5,6], weights=D)[0]
            stair += roll2
    return stair

def monte_carlo_probability(num_trials: int, T: int, D):
    success_count = 0
    for _ in range(num_trials):
        final_stair = rolldice(T, D)
        if final_stair > 200:
            success_count += 1
    return success_count / num_trials

# 示例:运行10000次模拟
prob = monte_carlo_probability(10000, 100, [0.2,0.2,0.2,0.2,0.1,0.1])
print(f"近似概率:{prob:.4f}")

说明

  • 模拟次数越多,结果越接近真实概率,通常1万-10万次模拟就能得到足够精确的结果
  • 优化后的代码去掉了不必要的打印,合并了条件判断,同时修正了第二次掷骰子的分布问题

方法二:动态规划(精确解)

如果需要精确概率,可以使用动态规划(DP)来计算每个投掷次数下,处于各台阶数的概率。为了减少状态数,我们可以将所有≥201的台阶合并为一个状态(因为我们只关心是否超过200)。

动态规划实现

def dp_probability(T: int, D):
    # dp[t][s] 表示第t次投掷后,处于s级台阶的概率
    # 状态s:0到200,201代表所有≥201的台阶
    max_stair = 200
    # 初始化:第0次投掷后,处于0级的概率为1
    dp_prev = [0.0] * (max_stair + 2)
    dp_prev[0] = 1.0

    for _ in range(T):
        dp_curr = [0.0] * (max_stair + 2)
        for s in range(max_stair + 2):
            if dp_prev[s] == 0:
                continue
            # 遍历所有可能的第一次掷骰子结果
            for roll1 in range(1,7):
                p1 = D[roll1-1]
                if roll1 in (1,2):
                    # 向下移动1级,或停在0级
                    new_s = max(s - 1, 0)
                    dp_curr[new_s] += dp_prev[s] * p1
                elif roll1 in (3,4,5):
                    # 向上移动1级
                    new_s = s + 1
                    if new_s > max_stair:
                        new_s = max_stair + 1
                    dp_curr[new_s] += dp_prev[s] * p1
                elif roll1 == 6:
                    # 第二次掷骰子,遍历所有可能结果
                    for roll2 in range(1,7):
                        p2 = D[roll2-1]
                        new_s = s + roll2
                        if new_s > max_stair:
                            new_s = max_stair + 1
                        dp_curr[new_s] += dp_prev[s] * p1 * p2
        dp_prev = dp_curr

    # 最终概率是所有≥201的状态的概率和
    return dp_prev[max_stair + 1]

# 计算精确概率
prob_exact = dp_probability(100, [0.2,0.2,0.2,0.2,0.1,0.1])
print(f"精确概率:{prob_exact:.6f}")

说明

  • 动态规划通过状态转移精确计算每个步骤的概率,没有随机误差
  • 将≥201的台阶合并为一个状态,避免了状态数无限增长的问题,计算量可控

内容的提问来源于stack exchange,提问作者Gavin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:15:40