愛麗絲參與一個大致基於紙牌遊戲 “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 = 10 的 6 種可能下,她的得分不超過 N = 6 分。
示例 3:
輸入:N = 21, K = 17, W = 10 輸出:0.73278
提示:
0 <= K <= N <= 10000
1 <= W <= 10000
- 如果答案與正確答案的誤差不超過
10^-5
,則該答案將被視爲正確答案通過。 - 此問題的判斷限制時間已經減少。
這道題真的就有點難
說一下解題思路
/*
* 例如N=3,K=2,W=3 我們要求的實際是 i=[1,2,3]中,i=2的概率+i=3的概率
* 我們可以從頭開始推,當手中沒有牌時,你抽到1的概率是 1/3也就是dp[1]=1/w
* 當i=2時的方法有兩種: 手中牌是0, 你直接抽到2 這時概率是 A=1/3=1/w
* 手中牌是1, 你抽到1 這時的概率是 B=1/3*1/3=(1/w)*(1/w) 這裏用的是條件概率的算法
* 最終 dp[2]=A+B
* 因爲當i<=w的時候,你是可以直接抽到一張牌符合結果的
* 所以,當i<=w的時候 dp[1]=1/w,dp[2]=dp[1]*1/w+1/w,dp[3]=dp[1]*1/w+dp[2]*1/w+1/w ... dp[i] = sum(dp[1,i-1])/w+1/w
* 當i>w的時候沒有辦法取一次得到結果,所以不用加上1/w了,例如:N=6,K=4,W=2
* 當i=3時,有2種取法1+2,2+1 沒有辦法從0直接到3,也就沒有1/w了
* dp[1]=1/w,dp[2]=dp[1]/w+1/w,dp[3]=sum(dp[1,2])/w
* 當i=4時有兩種取法2+2,3+1 , dp[4]=sum(dp[2,3])/w=(sum(dp[1,3])-dp[1])/w=(sum(dp[w+1,i])-dp[i-w])/w
* 因爲i的最大值是N所以dp的長度就是N+1
* 最終解爲sum(dp[K,N])
* 而當N >=(K + W)時 所有種k和w的和都不會超出N所以解是 1
*/
#include <iostream>
using namespace std;
double new21Game(int N, int K, int W) {
int i;
double dp[10002];
double sum = 0;
dp[0] = 1;
if(K > 0){
sum = sum + 1;
}
for(i = 1; i <= N; i++){
dp[i] = sum / W;
if(i < K){
sum += dp[i];
}
if(i >= W){
sum -= dp[i - W];
}
}
double ans = 0;
for(i = K; i <= N; i++){
ans += dp[i];
}
return ans;
}
int main(){
double re = new21Game(21, 17, 10);
cout << re << endl;
}