LeetCode 837. 新21点 (DP、全概率公式、前缀和)

新21点

  • 题意
    爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:
    爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W] 的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。
    当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?

  • 状态
    将K当成是可以使用的权限值。那么每抽取一个数字,权限值少一点,累积的分数多一点
    f ( k ) f(k) f(k)表示当爱丽丝以权限值为 k k k时,继续这场游戏获胜的概率(这个时候,累积分数为 K − k K-k Kk )。

那么我们的答案其实就是 f ( K ) f(K) f(K)

  • 状态转移方程
    f ( k ) = 1 / w ∗ ( f ( k − 1 ) + f ( k − 2 ) + … … + f ( k − w ) ) f(k) = 1/w*(f(k-1)+f(k-2)+……+f(k-w)) f(k)=1/w(f(k1)+f(k2)++f(kw))
    其实就是全概率公式。

  • 注意点
    注意到,权限值会从 K K K一直减少到 0 0 0,也可能一下子转移到负数,相当于最后一次抽取一下子全用光了权限值(并且还不够)。
    那么基本状态其实就是:
    f ( K − N ) = f ( K − N + 1 ) = … … = … … f ( 0 ) = 0 f(K-N)=f(K-N+1)=……=……f(0)=0 f(KN)=f(KN+1)==f(0)=0
    注意 f ( K − N − 1 ) 、 f ( K − N − 2 ) 、 … … f(K-N-1)、f(K-N-2)、…… f(KN1)f(KN2)等等概率都为0,因为这个时候相当于累积分数超过了 N N N
    由于负数不能作为数组下标,还要做一个线性映射。

  • 优化
    用一个前缀和优化是很明显的。

class Solution {
    
    
public: 
    double new21Game(int N, int K, int W) {
    
    
        double f[20010] = {
    
    0}, sf[20010] = {
    
    0},v = 1.0/W;
        // K-x-10000 <= N-10000;    K - x' <= N-10000;   x'>= K-N+10000;
        // x+10000 <= 10000;        x' <=  10000
        // x  <------> x+10000; 
        // f[x] = v*f[x-1]+v*f[x-2]+…………+v*f[x-W]; 
        // f[x+10000] = v*( f[x-1+10000] +  ……………… + f[x-W+10000] );
        for(int x=id(K-N);x<=id(0);x++){
    
    
            f[x] = 1;
            sf[x] = sf[x-1] + f[x];
        }

        for(int x=id(1);x<=id(K);x++){
    
    
            // f[x] = v*( sf[x-W,x-1]    );
            f[x] = v*(sf[x-1]-sf[x-W-1]);
            sf[x] = sf[x-1] + f[x];
        }
        return f[id(K)];
    }
    int id(int x){
    
    
        return x+10000;
    }
};
  • 另一种状态表示
  • d p [ x ] dp[x] dp[x]表示累计得分为 x x x的情况下,获胜的概率;
  • 基本状态: d p [ x ] = 1 ( K < = x < = m i n ( N , K − 1 + W ) ) dp[x]=1(K<=x<=min(N,K-1+W)) dp[x]=1(K<=x<=min(N,K1+W))
  • 转移方程: d p [ x ] = 1 / W ∗ ( d p [ x + 1 ] + d p [ x + 2 ] ) + … … + d p [ x + W ] dp[x]=1/W*(dp[x+1]+dp[x+2])+……+dp[x+W] dp[x]=1/W(dp[x+1]+dp[x+2])++dp[x+W]
  • 目标值: d p [ 0 ] dp[0] dp[0],(因为一开始得分为0)
  • 差分优化或者后缀和优化。

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/109071718