题目描述
爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:
爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W]
的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。
当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/new-21-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
算法思路
就这道题读题就给我读了半天,差点到了看题解都不理解的地步了。
第一版:
class Solution:
def new21Game(self, N: int, K: int, W: int) -> float:
if N<K:return 0.0
if K-1+W<=N or K==0:return 1.0
dp=[0]*(N+1)
dp[0]=1
for i in range(1,N+1):
left=max(0,i-W)
right=min(K,i)
for j in range(left,right):
dp[i]+=dp[j]/W
return sum(dp[K:N+1])
然后又被暴力超时制裁了。
因为重复计算了很多,所以:
class Solution:
def new21Game(self, N: int, K: int, W: int) -> float:
if N<K:return 0.0
if K-1+W<=N or K==0:return 1.0
dp=[0]*(N+1)
dp[0]=1
mp=0
for i in range(1,N+1):
if i-W<=0 and i<=K:
mp+=dp[i-1]
elif i>K and i-W>0:
mp-=dp[i-W-1]
elif i-W>0 and i<=K:
mp=mp-dp[i-W-1]+dp[i-1]
dp[i]+=mp/W
return sum(dp[K:N+1])
写着写着发现,哦:
class Solution:
def new21Game(self, N: int, K: int, W: int) -> float:
if N<K:return 0.0
if K-1+W<=N or K==0:return 1.0
dp=[0]*(N+1)
dp[0]=1
mp=0
for i in range(1,N+1):
if i<=K:
mp+=dp[i-1]
if i-W>0:
mp-=dp[i-W-1]
dp[i]+=mp/W
return sum(dp[K:N+1])
class Solution:
def new21Game(self, N: int, K: int, W: int) -> float:
if N<K:return 0.0
if K-1+W<=N or K==0:return 1.0
dp=[0]*(N+1)
dp[0]=1
mp=0
res=0
for i in range(1,N+1):
if i<=K:
mp+=dp[i-1]
if i-W>0:
mp-=dp[i-W-1]
dp[i]+=mp/W
if i>=K:
res+=dp[i]
return res