Leetcode 837. 新21点【动态规划】

问题描述

爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:

爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W] 的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。

当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?

示例 1:

输入:N = 10, K = 1, W = 10
输出:1.00000
说明:爱丽丝得到一张卡,然后停止

解题报告

(1) 在 i 不超过 w 的前提下, 爱丽丝取得分数 i 的可能情况为:

  • 最后一次抽到 1 加上爱丽丝取得分数 i-1 的各种情况;
  • 最后一次抽到 2 加上爱丽丝取得分数 i-2 的各种情况
  • ……
  • 最后一次抽到 i-1 加上爱丽丝取得分数 1 的各种情况;
  • 最后一次抽到 i 加上爱丽丝取得分数 0 的各种情况;

(2) 当 i 超过 w 时,爱丽丝取得分数 i 的可能情况为:

  • 最后一次抽到 1 加上爱丽丝取得分数 i-1 的各种情况;
  • 最后一次抽到 2 加上爱丽丝取得分数 i-2 的各种情况
  • ……
  • 最后一次抽到 w-1 加上爱丽丝取得分数 i-w+1 的各种情况;
  • 最后一次抽到 w 加上爱丽丝取得分数 i-w 的各种情况;

(3) 由于爱丽丝获得不少于 K 分时,停止抽取数字,所以,
i 超过 K 时,爱丽丝取得分数 i 的可能情况为:

  • 爱丽丝取得分数 K-1 加上最后一次抽到 i-K+1
  • 爱丽丝取得分数 K-2 加上最后一次抽到 i-K+2
  • ……
  • 爱丽丝取得分数 2 加上最后一次抽到 i-2
  • 爱丽丝取得分数 1 加上最后一次抽到 i-1

dp[i] 表示获取分数 i 的概率。具体实现看代码。

实现代码

class Solution {
public:
    double new21Game(int n, int k, int w) {
        if(k==0)return 1;
        if(n==0||k>n)return 0;
        vector<double>dp(n+1,0.0);
        // dp[i]表示的是当总分为i的时候的概率,最终的答案一定是k<=i<=n的所有概率之和,表示的是当取到分数大于k小于n的概率
        double sum=1.0;
        double res=0.0;
        dp[0]=1.0;
        for(int i=1;i<=n;i++){
            dp[i]=1.0*sum/w;
            if(i<k){
                sum+=dp[i];
            }else{
                res+=dp[i];//表示当前选的点是符合要求的,那么将其加入到符合条件的概率当中
            }
            if(i>=w){
                sum-=dp[i-w];//sum表示的是中间只能有w个数据,
            }
        }
        for(int i=0;i<dp.size();i++)cout<<dp[i]<<" ";
        cout<<endl;
        return res;
    }
};

参考资料

[1] Leetcode 837. 新21点
[2] 题解区:zb121

猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/106521565