leetcode837. 新21點/動態規劃

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

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

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

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

基本思想

這道題當初的思想是枚舉所有的結果,並統計次數;並計算結果中不超過N的次數,二者相比求概率。這個思想的錯誤在於:每一種組合並不是等概率出現的。
例如:K = 3, N = 3, W = 2。對於 1,2 和1,1,2,這兩種情況出現的概率不相等前者出現的概率是1/4,後者是1/8.

動態規劃:

  • dp[i]:當前分數爲 i 時,獲勝的概率。也就是說,當前抽取的和爲 i ,再抽取一張有多大概率能獲勝。那麼最終結果就是dp[0]
  • i 的範圍:i 最小爲0,最大爲 K - 1 + W(也就是當前和爲K - 1,還能在抽取一次,再抽取一次的結果最大是W)
  • 初始值:當i >= K 且 i < = N時,dp[i] = 1;當 i >= K且i > N時,dp[i] = 0。(說明:N和K-1+W的大小關係是不確定的,如果N>=K-1+W最終結果一定是1)
  • 狀態轉移方程:當前爲i的情況下,抽取每一張牌的概率爲1/W,獲勝的概率爲其對應的dp值dp[i]=dp[i+1]+dp[i+2]+dp[i+3]++dp[i+W]Wdp[i] = \frac{dp[i+1]+dp[i+2]+dp[i+3]+…+dp[i+W]}{W}
  • 代碼中,狀態轉移方程需要求當前元素後面W項的和,用sum來計算
class Solution {
public:
    double new21Game(int N, int K, int W) {
        //定義dp
        //dp[i]:當前得分爲i的情況下,分數不超過N的概率
        //i最大爲:K—1+W
        if(K - 1 + W <= N)//當累計的最終結果的最大值不超過N,最終概率爲1
            return 1;
        vector<double> dp(K + W, 0);
        //初始化:當前得分>=K,分數不超過N的概率爲1,因爲無需再抽取數字
        for(int i = K; i < K + W && i <= N; ++i)
            dp[i] = 1;
        double sum =  N - K + 1;//初始時,1的個數
        for(int i = K - 1; i >= 0; --i){
            dp[i] = sum / W;
            sum = sum + dp[i] - dp[i + W];
        }
        return dp[0];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章