Leetcode——837. 新21點 概率Dp

愛麗絲參與一個大致基於紙牌遊戲 “21點” 規則的遊戲,描述如下:

愛麗絲以00 分開始,並在她的得分少於 K 分時抽取數字。 抽取時,她從 [1,W][1, W] 的範圍中隨機獲得一個整數作爲分數進行累計,其中 WW 是整數。 每次抽取都是獨立的,其結果具有相同的概率。

當愛麗絲獲得不少於 KK 分時,她就停止抽取數字。 愛麗絲的分數不超過 NN的概率是多少?

示例 1:

輸入:N = 10, K = 1, W = 10
輸出:1.00000
說明:愛麗絲得到一張卡,然後停止。

示例 2:

輸入:N = 6, K = 1, W = 10
輸出:0.60000
說明:愛麗絲得到一張卡,然後停止。
在 W = 10 的 6 種可能下,她的得分不超過 N = 6 分。

示例 3:

輸入:N = 21, K = 17, W = 10
輸出:0.73278

提示:

0KN100000 \le K \le N \le 10000
1W100001 \le W \le 10000
如果答案與正確答案的誤差不超過 10510^{-5},則該答案將被視爲正確答案通過。
此問題的判斷限制時間已經減少。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/new-21-game
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

因爲最終的概率是和下一輪開始前的得分有關的,因此我們可以根據得分計算下面的概率。
dp[x]dp[x]表示得分爲xx的情況下開始玩遊戲並且獲勝的概率。那麼就可以確定所需要的求的答案是dp[0]dp[0]
根據題意,當分數大於等於KK的時候遊戲結束,如果遊戲結束的時候,如果分數不超過NN就獲得勝利。如果分數超過NN就失敗。那麼當
dp[x]={dp[x]=1Kxmin(N,K+W1)dp[x]=0x>min(N,K+W1)dp[x] = \begin{cases}dp[x] = 1 \quad K \le x \le \min(N,K+W-1) \\ dp[x] = 0\quad x > min(N,K+W-1)\end{cases}

這是因爲不超過K的時候能夠最大的數字是K1K-1,此時可以抽一次,最大值爲WW,所以得到的最大分數爲K+W1K+W-1

那麼當0x<K0\le x < K的時候。每一個xx得分可以轉移WW個狀態,因爲在xx的狀態下可以抽取的範圍爲[1,W][1,W],每個數字的概率爲1W\frac{1}{W}。所以dp[x]dp[x]可以表示爲:
dp[x]=dp[x+1]++dp[x+W]Wdp[x] = \frac{dp[x+1]+\cdots + dp[x+W]}{W}

所以根據這個狀態轉移方程,可以計算出最後的答案,但是我們會發現,這個狀態轉移的時間複雜度有點高O(KW)O(KW)
但是一般動態規劃都是相鄰項之間的轉移,那麼我們看看相鄰項之間的關係。

dp[x]=dp[x+1]++dp[x+W]Wdp[x] = \frac{dp[x+1]+\cdots + dp[x+W]}{W}
dp[x+1]=dp[x+1+1]++dp[x+1+W]Wdp[x+1] = \frac{dp[x+1+1]+ \cdots + dp[x+1+W]}{W}
所以可以得到了
dp[x]dp[x+1]=dp[x+1]dp[x+W+1Wdp[x]-dp[x+1] = \frac{dp[x+1]-dp[x+W+1}{W}
dp[x]=dp[x+1]dp[x+1]dp[x+W+1]Wdp[x] = dp[x+1] -\frac{dp[x+1]-dp[x+W+1]}{W}
其中0x<K10\le x<K-1
注意xx的取值範圍哦,所以我們需要單獨處理K1K-1
因此我們可以在O(1)O(1)的範圍內得到轉移方程。

func min(a,b int)int {
    if a > b{
        return b
    }
    return a
}
func new21Game(N int, K int, W int) float64 {
    if K== 0{
        return 1.0
    }
    dp := make([]float64, K+W+1)
    for i:=K;i<=N && i<K+W;i++{
        dp[i] = 1.0
    }
    dp[K-1] = 1.0 * float64(min(N-K+1, W))/float64(W)
    for i:=K-2;i>=0;i--{
        dp[i] = dp[i+1] -(dp[i+W+1] -dp[i+1])/float64(W)
    }
    return  dp[0]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章