837. 新21点

Medium

思路

首先进行阅读理解

阅读理解结束,开始思考过程

掷两次骰子,求两次骰子和在4-6之间的概率
4的可能的组合为: (1,3)、(2,2)、(3,1)
5的可能的组合为: (2,3)、(3,2)
6的可能的组合为: (1,5)、(2,4)、(3,3)、(4,2)、(5,1)
P(sum) = P(4) + P(5) + P(6) = 3/36 + 2/36 + 5/36 = 5/18

使用记忆化递归,TLE

python3

class Solution:
    @lru_cache(None)
    def dfs(self, cur, N, K, W):
      if cur >= K:
        if cur <= N:
          return 1
        else:
          return 0
      sum = 0
      for i in range(1, W+1):
        sum += 1.0 / W * self.dfs(cur + i, N, K, W)
      return sum
    def new21Game(self, N: int, K: int, W: int) -> float:
      return self.dfs(0,N,K,W)

TLE,需要更新思路 记忆化递归通常我们可以转成dp,bottom-up方式来优化。

拜读大佬解法,获得新思路

概率分析
动态规划

综上,进行尝试,TLE。我真的是太难了。。

python3

class Solution:
    def new21Game(self, N: int, K: int, W: int) -> float:
      dp = [None] * (N + 1)
      dp[0] = 1
      for i in range(1, N + 1):
        left = 0 if (i-W) < 0 else (i-W)
        right = i if i <= K else K 
        dp[i] = sum(dp[left:right]) * (1/W)
      return sum(dp[K:])

还需进行优化

综上,进行尝试,AC!

代码

python3

class Solution:
    def new21Game(self, N: int, K: int, W: int) -> float:
      dp = [None] * (N + 1)
      dp[0] = 1
      presum = 0
      for i in range(1, N + 1):
        if i-W > 0:
          presum -= dp[i-W-1]
        if i <= K:
          presum += dp[i-1]
        dp[i] = presum * (1/W)
      return sum(dp[K:])