ริมาเริ่มต้น 0 คะแนน จั่วไพ่ได้คะแนนสุ่ม 1 ถึง W จนกว่าจะได้ ≥ K คะแนน หาความน่าจะเป็นที่คะแนนสุดท้าย ≤ N
ตัวอย่าง
Input − N=6, K=1, W=10 Output − 0.6
คำอธิบาย − จั่ว 1 ครั้งหยุด (K=1) โอกาสได้ 1-6 คือ 6/10 = 0.6
แนวทางการแก้ปัญหา (Dynamic Programming + Sliding Window)
- dp[i] = ความน่าจะเป็นที่ได้คะแนน i
- dp[0] = 1
- สำหรับ i=1..N: dp[i] = (dp[i-1] + ... + dp[i-W]) / W (ใช้ sliding window sum)
- ถ้า i < K: ยังจั่วต่อ → เพิ่มเข้า window sum
- ถ้า i ≥ K: หยุดจั่ว → บวกเข้า answer
- ลบ dp[i-W] ออกจาก window เมื่อ i ≥ W
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
double new21Game(int N, int K, int W) {
if (K == 0 || N >= K + W) return 1.0;
vector dp(N + 1, 0);
dp[0] = 1;
double windowSum = 1, ans = 0;
for (int i = 1; i <= N; i++) {
dp[i] = windowSum / W;
if (i < K) windowSum += dp[i];
else ans += dp[i];
if (i >= W) windowSum -= dp[i - W];
}
return ans;
}
};
int main() {
Solution ob;
cout << fixed << setprecision(1) << ob.new21Game(6, 1, 10); // 0.6
return 0;
}
ผลลัพธ์
0.6
บทความนี้แก้ปัญหา New 21 Game (LeetCode 837) โดยใช้ DP + Sliding Window คำนวณความน่าจะเป็นได้แต่ละคะแนน O(N) time O(N) space