[滑动窗口]837. 新 21 点

837. 新 21 点

837. 新 21 点 - 力扣(LeetCode)

算法思路

  1. 1.问题分析​:游戏规则是每次抽取的点数为1到maxPts的均匀分布。当分数≥k时停止,求最终分数≤n的概率。
  2. 2.​动态规划定义​:定义f[i]为当前分数为i时,最终停止时分数≤n的概率。
  3. 3.​边界条件​:
    • •当i ≥ k时,停止抽牌。若i ≤ n,则概率为1(成功);若i > n,则概率为0(失败)。但数组大小仅为n+1(0到n),所以只考虑i≤n的情况:f[i] = 1.0
  4. 4.状态转移​(当i < k时):
    • •需要继续抽牌,概率为所有下一可能状态的均值:f[i] = (f[i+1] + f[i+2] + ... + f[i+maxPts]) / maxPts
    • •用滑动窗口维护和:用变量s保存当前需要的连续区间和(长度最多为maxPts)。
  5. 5.​逆序计算​:从后往前(in递减到0)计算f[i]
    • •当前s维护的是f[i+1]f[i+maxPts]的和(但不超过数组范围)。
    • •计算f[i]后,更新s = s + f[i](添加新状态)。
    • •若窗口超过maxPts(即i + maxPts <= n),则移除末尾元素:s = s - f[i+maxPts]
  6. 6.​初始化​:s = 0.0,数组f初始化为全0。
class Solution:
    def new21Game(self, n: int, k: int, maxPts: int) -> float:
        f = [0.0] * (n + 1)  # 初始化DP数组,大小为n+1(0到n)
        s = 0.0  # 滑动窗口的和
        # 从后往前遍历i(n到0)
        for i in range(n, -1, -1):
            if i >= k:
                f[i] = 1.0  # 停止抽牌,i≤n时概率为1
            else:
                f[i] = s / maxPts  # 状态转移:均值
            s += f[i]  # 将f[i]加入窗口
            if i + maxPts <= n:
                s -= f[i + maxPts]  # 维护窗口大小(移除超出部分)
        return f[0]  # 返回从0开始的概率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值