題目描述
愛麗絲參與一個大致基於紙牌遊戲 “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