837. New 21 Game

更新 發佈閱讀 7 分鐘

[Medium] 解法 : DP + sliding window

題意 :

給定 nkmaxPts

  • 起始分數為 0。
  • 當分數小於 k 時,會隨機抽一個介於 1 到 maxPts 的整數點數,每次抽牌機率相同且獨立。
  • 當分數達到或超過 k 時停止抽牌。

回傳最終分數 不超過 n 的機率。

解題思路 :

給定k的情況下,在 k-1時抽到maxPts可讓拿到分數最大,最大值為k+maxPts-1

因此在停止抽牌時,可以拿到的分數如下 :

[k, k+1, ..., k+maxPts-1]

可以歸類出 3 種例外狀況

  • k == 0 : 不能抽牌,分數為0,顯然 <= n
  • n >= (k + maxPts - 1) : 結束抽牌時,分數最大為(k + maxPts - 1),永遠 <= n
  • n < k : 結束抽牌時,分數最小為 k,分數不可能 <= n
// 特殊情況處理
if (k == 0) return 1.0;               // 不需要抽牌就結束
if (n < k) return 0.0;                // 沒有機會到達目標
if (n >= k + maxPts - 1) return 1.0;  // 範圍足夠,必定成功

剩下情況以DP方式逐步推得解。會有一陣列pp[i]代表的意思可以抽牌的情況下,抽牌後可讓點數為 i 的機率。

從 [1, maxPts] 抽取任一張牌的機率皆為 1/maxPts,要讓點數為 i 的機率可以由以下來推得。(假設 maxPts = 5)

// i=1
p(1) = 1/5*p(0) (抽了分數為1的牌)
// i=2
p(2) = 1/5*p(1) +1/5*p(0) (抽了分數為1的牌) + (抽了分數為2的牌)
// i=3
p(3) = 1/5*p(2) +1/5*p(1) +1/5*p(0)
// i=4
p(4) = 1/5*p(3) +1/5*p(2) +1/5*p(1) +1/5*p(0)
// i=5
p(5) = 1/5*p(4) +1/5*p(3) +1/5*p(2) +1/5*p(1) +1/5*p(0)
// i=6
p(6) = 1/5*p(5) +1/5*p(4) +1/5*p(3) +1/5*p(2) +1/5*p(1)

可觀察到規律, p[i]的值可由前面求出的機率值推出 (p[i-1]、p[i-2]...等)

因此可用 sliding window,並以 windowSum紀錄先前求出機率的和

// i=1
p(1) = 1/5*windowSum (windowSum = p(0))
// i=2
p(2) = 1/5*windowSum (windowSum = p(0)+p(1))
// i=3
p(3) = 1/5*windowSum (windowSum = p(0)+p(1)+p(2))
// i=4
p(4) = 1/5*windowSum (windowSum = p(0)+p(1)+p(2)+p(3))
// i=5
p(5) = 1/5*windowSum (windowSum = p(0)+p(1)+p(2)+p(3)+p(4))
// i=6
p(6) = 1/5*windowSum (windowSum = p(1)+p(2)+p(3)+p(4)+p(5))

每次更新 p[i]時都會將 p[i-1]加進windowSum,但如果(i-1) >= k代表累積分數 (i-1)已經達到停止抽牌的門檻,因此沒辦法進行抽牌使分數變成 i,所以在這情況下 p[i-1]不會被加進windowSum

在更新windowSum有以下要注意:

  • i ≤ maxPtswindowSum 可直接累加先前的 p 值,因可累加範圍還未滿。
  • i > maxPts,視窗長度已滿,要將整個視窗 shift 一格

shift 一格時會需要剃除舊有的值,因此會用 l變數作為 window 最左邊下次需要被剃除的機率索引。

最後p[k]+p[k+1]+...p[n]即是答案

class Solution {
public:
    double new21Game(int n, int k, int maxPts) {
        // 特殊情況處理
        if (k == 0) return 1.0;               // 不需要抽牌就結束
        if (n < k) return 0.0;                // 沒有機會到達目標
        if (n >= k + maxPts - 1) return 1.0;  // 範圍足夠,必定成功

        vector<double> p(n+1, 0); // p[i] : 可以抽牌的情況下,抽牌後可讓點數為 i 的機率
        p[0] = 1;
        double windowSum = 0;
        int l = 0;

        for(int i=1 ; i<=n ; ++i){
            // (i-1) < k 時代表可以執行抽牌的動作
            if(i-1 < k)
                windowSum += p[i-1];
            // 執行 shift 動作
            if(i > maxPts){
                windowSum -= p[l];
                ++l;
            }
            p[i] = windowSum / maxPts;
        }
        return accumulate(p.begin() + k, p.end(), 0.0);
    }
};


Extra :

題目有點抽象,看了 contest rating 難度為 2350 分。看懂機率求得的過程花了不少時間@@









留言
avatar-img
Leetcode 練習 🔥
0會員
5內容數
一些自己解題思路的筆記,也希望可以幫助到需要的人 !
Leetcode 練習 🔥的其他內容
2025/07/30
[Medium] 解法 : BFS 題意 : 給定一個長度為 n 的整數陣列 nums,從索引 0 開始,目標是走到索引 n - 1。 對於任意索引 i,可進行以下操作: 相鄰跳躍:索引仍在陣列範圍內,可以跳到 i + 1 或 i - 1。 質數傳送:如果 nums[i] 是一個質數
2025/07/30
[Medium] 解法 : BFS 題意 : 給定一個長度為 n 的整數陣列 nums,從索引 0 開始,目標是走到索引 n - 1。 對於任意索引 i,可進行以下操作: 相鄰跳躍:索引仍在陣列範圍內,可以跳到 i + 1 或 i - 1。 質數傳送:如果 nums[i] 是一個質數
2025/07/19
[Medium] 解法 : BFS 題意 : 給定一個二維陣列,元素為整數,與一個整數 k。其中被 0 圍起來的整數區塊為 island,island value 為區塊內元素數值的總和。一個合法的小島是其 value 可以被 k 整除,求出符合此條件的所有小島,並將 value 加總回傳。
Thumbnail
2025/07/19
[Medium] 解法 : BFS 題意 : 給定一個二維陣列,元素為整數,與一個整數 k。其中被 0 圍起來的整數區塊為 island,island value 為區塊內元素數值的總和。一個合法的小島是其 value 可以被 k 整除,求出符合此條件的所有小島,並將 value 加總回傳。
Thumbnail
2025/07/15
[Easy] 解法 : Traversal 題意 : 給定一個字串,判斷其是否合法。合法的條件如下,全部皆需要滿足 最少需要 3 個字元 字串中只能含有英文字母與數字 字串中至少要有一個母音 (vowel) 字串中至少要有一個子音 (consonant) 解題思路 : 用一個 s
Thumbnail
2025/07/15
[Easy] 解法 : Traversal 題意 : 給定一個字串,判斷其是否合法。合法的條件如下,全部皆需要滿足 最少需要 3 個字元 字串中只能含有英文字母與數字 字串中至少要有一個母音 (vowel) 字串中至少要有一個子音 (consonant) 解題思路 : 用一個 s
Thumbnail
看更多
你可能也想看
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
24點數學遊戲是一款適合小朋友與想動動腦的朋友們的小遊戲,遊戲規則簡單易懂,可訓練邏輯能力。遊戲分為單人與多人模式,可以讓玩家自行挑戰高分或是與其他玩家競爭。算式中不同的數學符號會對應不同的加分機制。遊戲網站連結與專案 repo 也都提供在文章中。
Thumbnail
24點數學遊戲是一款適合小朋友與想動動腦的朋友們的小遊戲,遊戲規則簡單易懂,可訓練邏輯能力。遊戲分為單人與多人模式,可以讓玩家自行挑戰高分或是與其他玩家競爭。算式中不同的數學符號會對應不同的加分機制。遊戲網站連結與專案 repo 也都提供在文章中。
Thumbnail
原版的官方規則導入記分機制,但因為計算過於繁複,所以一般遊玩時較少採用。本變體規則旨在還原原規則的策略性,並保留平常的遊玩樂趣。 1. 配件準備 4枚不同顏色的棋子(紅、藍、黃、綠),以及一張標記0~15的場地。 2. 記分方式 一開始所有棋子都在0的位置。每一局結束時,贏家以外的所有人拿出
Thumbnail
原版的官方規則導入記分機制,但因為計算過於繁複,所以一般遊玩時較少採用。本變體規則旨在還原原規則的策略性,並保留平常的遊玩樂趣。 1. 配件準備 4枚不同顏色的棋子(紅、藍、黃、綠),以及一張標記0~15的場地。 2. 記分方式 一開始所有棋子都在0的位置。每一局結束時,贏家以外的所有人拿出
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
知道如何從一組給定的英文字母和單字庫中的單字拼出最高分的單字組合。使用DFS + 回溯法 + 剪枝優化的演算法,詳細分析瞭如何展開所有可能的路徑,並且找出符合條件的狀態,協助讀者理解演算法背後的思維和方法。
Thumbnail
知道如何從一組給定的英文字母和單字庫中的單字拼出最高分的單字組合。使用DFS + 回溯法 + 剪枝優化的演算法,詳細分析瞭如何展開所有可能的路徑,並且找出符合條件的狀態,協助讀者理解演算法背後的思維和方法。
Thumbnail
本篇文章介紹了區間DP及博弈論Min/Max最佳化的相關概念,以及如何應用這些概念來計算最佳策略進行取石頭遊戲的模擬。文章實際分析了演算法、實用的加速技巧和關鍵知識點。這篇文章對於想要學習區間DP的讀者來說非常有價值。
Thumbnail
本篇文章介紹了區間DP及博弈論Min/Max最佳化的相關概念,以及如何應用這些概念來計算最佳策略進行取石頭遊戲的模擬。文章實際分析了演算法、實用的加速技巧和關鍵知識點。這篇文章對於想要學習區間DP的讀者來說非常有價值。
Thumbnail
題目敘述 輸入給定一個二元的二維矩陣grid 每次可以翻轉一條row,讓每個元素的01反相。 也可以翻轉一條column,讓每個元素的01反相。 可以操作任意多次。 最後把每條row視為一條二進位表達式的數字,並且進行加總,得到最後的分數。 請問分數的最大值是多少? 原本的英文題目敘
Thumbnail
題目敘述 輸入給定一個二元的二維矩陣grid 每次可以翻轉一條row,讓每個元素的01反相。 也可以翻轉一條column,讓每個元素的01反相。 可以操作任意多次。 最後把每條row視為一條二進位表達式的數字,並且進行加總,得到最後的分數。 請問分數的最大值是多少? 原本的英文題目敘
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News