每日一題 新21點 概率題目

2021-10-06 18:48:04 字數 1747 閱讀 7018

2020/06/03 一道穿了概率外衣的dp問題

思路核心在於如何理解題意,這個概率是如何計算得到的。

有兩種思路,第一種思路從前往後進行推導,但是我沒成功。暫且不表。

主要講一下比較好的第二種思路。既然是一道概率題,我們首先把遊戲結束時的成功的事件設定為1。成功事件是指,最後結果大於等於k且小於等於n的事件,與之相應的失敗時間是最後結果大於n。

由於最後的狀態只與前乙個狀態有關,因此我們設定狀態dp[i]表示當前數值為i時,成功的概率。

顯然dp[k: min(n,k+w)+1]= 1,其餘狀態都初始化為0。

轉移方程:dp[i] = sum(dp[i+1:i+w+1])/w。也就是對未來的w個狀態的概率加和並平均。這樣我們需要最後得到dp[0]即可。

class

solution

:def

new21game

(self, n:

int, k:

int, w:

int)

->

float

:# 時間複雜度o(kw+min(n-k,w))

if k ==0:

return

1 dp =[0

]*(w+k)

for i in

range

(k,min

(n, w+k)+1

):dp[i]=1

for i in

range

(k-1,-

1,-1

):# dp[i] = sum(dp[i+1:i+w+1])/w

for j in

range(1

,w+1):

dp[i]

+= dp[i+j]

/w return dp[

0]

但是這樣會超時,因此我們嘗試簡化dp。之前說過,如果dp超時常用的方法就是嘗試差分,看看能否的到更簡單的方法,尤其是對於這類dp的狀態轉換用到大量的累加的如果我們仔細觀察可以發現,dp[i+1]dp[i]的區別只有兩項,其實類似滑動窗,每次保持w項相加。因此我們可以簡化。

# 當發現dp超時,考慮利用差分簡化

# 時間複雜度o(min(n,w+k))

if k ==0:

return

1 dp =[0

]*(w+k)

for i in

range

(k,min

(n, w+k)+1

):dp[i]=1

dp[k-1]

=sum

(dp[k:k+w])/w

# 差分思路,去掉最右側乙個[i+w+1],增加左側的乙個[i+1]

for i in

range

(k-2,-

1,-1

):dp[i]

= dp[i+1]

+dp[i+1]

/w-dp[i+w+1]

/w return dp[

0]

LeetCode 每日一題 837 新21點

愛麗絲參與乙個大致基於紙牌遊戲 21點 規則的遊戲,描述如下 愛麗絲以 0 分開始,並在她的得分少於 k 分時抽取數字。抽取時,她從 1,w 的範圍中隨機獲得乙個整數作為分數進行累計,其中 w 是整數。每次抽取都是獨立的,其結果具有相同的概率。當愛麗絲獲得不少於 k 分時,她就停止抽取數字。愛麗絲的...

藍橋杯每日一題(21) 擴散(python)

小藍在一張無限大的特殊畫布上作畫。這張畫布可以看成乙個方格圖,每個格仔可以用乙個二維的整數座標表示。小藍在畫布上首先點了一下幾個點 0,0 2020,11 11,14 2000,2000 只有這幾個格仔上有黑色,其它位置都是白色的。每過一分鐘,黑色就會擴散一點。具體的,如果乙個格仔裡面是黑色,它 就...

每日一題力扣21 神奇的遞迴

將兩個公升序鍊錶合併為乙個新的 公升序 鍊錶並返回。新煉表是通過拼接給定的兩個鍊錶的所有節點組成的。class solution def mergetwolists self,l1 listnode,l2 listnode listnode ifnot l1 return l2 終止條件,直到兩個鍊...