【訓練題19:概率DP】One Person Game | ZOJ3329
難度
6
/
10
6/10
6/10
有一說一,是一道經典概率DP題,個人感覺至少省賽題。
但是看其他部落格都是隨便秒過的 ???
題意
你有三個骰子,分別有 K 1 , K 2 , K 3 K_1,K_2,K_3 K1,K2,K3面,每面投擲到的概率都相等,面上標號數字為 1 ∼ K i 1\sim K_i 1∼Ki
一開始,你的分數為
0
0
0。
每輪:你同時投擲三個骰子,如果第一個骰子頂面為
a
a
a 面 , 第二個骰子頂面為
b
b
b 面, 第三個頂面骰子為
c
c
c 面 ,那麼你的分數歸零。否則,你的分數增加三個骰子的頂面的和。
如果你的分數超過
n
n
n,遊戲結束
問你:遊戲開始到遊戲結束,你的投擲骰子次數的期望為多少?
要求答案誤差
∣
e
p
s
∣
<
1
0
−
8
|eps|<10^{-8}
∣eps∣<10−8
樣例輸入
組數,
T
T
T
n
K
1
K
2
K
3
a
b
c
n\ K_1\ K_2\ K_3\ a\ b\ c
n K1 K2 K3 a b c
2 0 2 2 2 1 1 1 0 6 6 6 1 1 1 2\\ 0\ 2\ 2\ 2\ 1\ 1\ 1\\ 0\ 6\ 6\ 6\ 1\ 1\ 1 20 2 2 2 1 1 10 6 6 6 1 1 1
樣例輸出
1.142857142857143 1.004651162790698 1.142857142857143\\ 1.004651162790698 1.1428571428571431.004651162790698
思路
- 首先,我們按照前人的經驗,期望得倒著推。
- 設 e ( i ) \color{cyan}e(i) e(i) 表示目前分數為 i i i , 到遊戲結束時的投擲次數的期望。
- 設 f ( i ) \color{cyan}f(i) f(i) 表示三個骰子投擲出點數和為 i i i 的概率。
- 特別地,設 f ( 0 ) f(0) f(0) 表示投擲後,第一個骰子頂面為 a a a 面 , 第二個骰子頂面為 b b b 面, 第三個頂面骰子為 c c c 面的概率。即,每次分數歸零的概率。
- 目前分數為
i
i
i , 我們投擲一次之後三面骰子分別為
w
1
,
w
2
,
w
3
w_1,w_2,w_3
w1,w2,w3
- 下次的分數可能為 i + w 1 + w 2 + w 3 i+w_1+w_2+w_3 i+w1+w2+w3,這個概率為 f ( w 1 + w 2 + w 3 ) f(w_1+w_2+w_3) f(w1+w2+w3)
- 下次的分數可能為 0 0 0 ,就是歸零了,這個概率為 f ( 0 ) f(0) f(0)
- 易得,如果已經分數超過
n
n
n 了,那麼遊戲直接結束,投擲次數期望為0,即:
- e ( > n ) = 0 e(>n)=0 e(>n)=0
- 我們最終的答案即為 e ( 0 ) e(0) e(0)
- 我們寫成式子就是 e ( i ) = ∑ K 1 + K 2 + K 3 k = 1 f ( k ) e ( i + k ) + f ( 0 ) e ( 0 ) + 1 \color{red}e(i)=\underset{k=1}{\overset{K_1+K_2+K_3}{\sum}} f(k)e(i+k) + f(0)e(0)+1 e(i)=k=1∑K1+K2+K3f(k)e(i+k)+f(0)e(0)+1
- (加一是因為多投擲了一次)
- 注意到,我們期望是逆推的 ( i i i 從大到小),答案為 e ( 0 ) e(0) e(0),但是其中每一個遞推式子都包括 e ( 0 ) e(0) e(0),這就很頭疼了!
【注】如果 e ( i ) e(i) e(i) 每一項遞推式是關於 e ( x ) ∧ ( x ≥ i ) e(x)\wedge (x\ge i) e(x)∧(x≥i),我們可以把遞推式子的右邊的 e ( i ) e(i) e(i) 項拎出來放在左邊,然後轉化為一個左邊只有 e ( i ) e(i) e(i) , 右邊關於 e ( x ) ∧ ( x > i ) e(x)\wedge (x> i) e(x)∧(x>i)的式子,可以直接遞推。
這 題 的 套 路 做 法 \color{red}這題的套路做法 這題的套路做法
- 設 e ( i ) = a ( i ) e ( 0 ) + b ( i ) \color{cyan}e(i)=a(i)e(0)+b(i) e(i)=a(i)e(0)+b(i)
- 我們帶入上述式子,得到:
e ( i ) = ∑ f ( k ) e ( i + k ) + f ( 0 ) e ( 0 ) + 1 = ∑ f ( k ) ( a ( i + k ) e ( 0 ) + b ( i + k ) ) + f ( 0 ) e ( 0 ) + 1 = ( ∑ f ( k ) a ( i + k ) + f ( 0 ) ) e ( 0 ) + ( ∑ f ( k ) b ( i + k ) + 1 ) = a ( i ) e ( 0 ) + b ( i ) \begin{aligned}e(i)&=\sum f(k)e(i+k)+f(0)e(0)+1\\ &=\sum f(k)\Big( a(i+k)e(0)+b(i+k) \Big)+f(0)e(0)+1\\ &=\Big(\sum f(k)a(i+k)+f(0)\Big)e(0)+\Big( \sum f(k)b(i+k)+1 \Big)\\ &=a(i)e(0)+b(i) \end{aligned} e(i)=∑f(k)e(i+k)+f(0)e(0)+1=∑f(k)(a(i+k)e(0)+b(i+k))+f(0)e(0)+1=(∑f(k)a(i+k)+f(0))e(0)+(∑f(k)b(i+k)+1)=a(i)e(0)+b(i) - 我們得到了:
{ a ( i ) = ∑ f ( k ) a ( i + k ) + f ( 0 ) b ( i ) = ∑ f ( k ) b ( i + k ) + 1 \begin{cases} \color{red}a(i)=\sum f(k)a(i+k)+f(0)\\ \color{red}b(i)=\sum f(k)b(i+k)+1 \end{cases} {a(i)=∑f(k)a(i+k)+f(0)b(i)=∑f(k)b(i+k)+1 - 注意到 e ( x > n ) = a ( x ) e ( 0 ) + b ( x ) = 0 e(x>n)=a(x)e(0)+b(x)=0 e(x>n)=a(x)e(0)+b(x)=0
- 我們得到 a ( > n ) = b ( > n ) = 0 a(>n)=b(>n)=0 a(>n)=b(>n)=0
- 最後答案為 e ( 0 ) = a ( 0 ) e ( 0 ) + b ( 0 ) e(0)=a(0)e(0)+b(0) e(0)=a(0)e(0)+b(0),即:
- 最終答案為 e ( 0 ) = b ( 0 ) 1 − a ( 0 ) \color{red}e(0)=\frac{b(0)}{1-a(0)} e(0)=1−a(0)b(0)
其他的細節可以參考一下程式碼。
核心程式碼
時間複雜度 O ( K 1 K 2 K 3 + n 2 ) O(K_1K_2K_3+n^2) O(K1K2K3+n2)
/*
_ __ __ _ _
| | \ \ / / | | (_)
| |__ _ _ \ V /__ _ _ __ | | ___ _
| '_ \| | | | \ // _` | '_ \| | / _ \ |
| |_) | |_| | | | (_| | | | | |___| __/ |
|_.__/ \__, | \_/\__,_|_| |_\_____/\___|_|
__/ |
|___/
*/
const int MAX = 550;
double a[MAX];
double b[MAX];
double f[MAX];
int main()
{
int KASE;
while(cin >> KASE){
while(KASE--){
int n,k1,k2,k3,aa,bb,cc;
cin >> n >> k1 >> k2 >> k3 >> aa >> bb >> cc;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(f,0,sizeof(f));
for(int i = 1;i <= k1;++i)
for(int j = 1;j <= k2;++j)
for(int k = 1;k <= k3;++k) /// 注意算 f(x)時候不要把歸零的答案算進去了
if(i != aa || j != bb || k != cc)f[i+j+k] += 1.0 / k1 / k2 / k3;
double f0 = 1.0 / k1 / k2 / k3;
for(int i = n;i >= 0;--i){
double t1 = f0,t2 = 1.0;
for(int k = 3;i + k <= n;++k){
t1 += f[k] * a[i + k];
t2 += f[k] * b[i + k];
}
a[i] = t1;
b[i] = t2;
}
printf("%.15f\n",b[0] / (1.0 - a[0]));
}
}
return 0;
}
相關文章
- dp專題訓練
- 做題小結 DP訓練
- 做題小結 dp訓練6
- 24.8.18 DP訓練
- POJ 3071 Football(概率DP)
- ACM日常訓練日記——8.1(區間dp)ACM
- ESPN NBA Basketball was the one franchise gameGAM
- 「日常訓練」 Soldier and Number Game (CFR304D2D)GAM
- luogu P6835 概率DP 期望
- acm訓練題ACM
- 「暑期訓練」「基礎DP」 Common Subsequence (POJ-1458)
- 「暑期訓練」「基礎DP」 Monkey and Banana (HDU-1069)NaN
- 19_04_02校內訓練[deadline]
- 2024.11.05 刷題訓練
- 【專題訓練】字串字串
- 19_03_26校內訓練[魔法卡片]
- 19_04_02校內訓練[圖染色]
- 19_03_28校內訓練[相似字串]字串
- dp加練
- [DP]HDU6415(2018多校訓練賽第九場 Problem A) Rikka with Nash Equilibrium 題解UI
- 「暑期訓練」「基礎DP」免費餡餅(HDU-1176)
- keras中VGG19預訓練模型的使用Keras模型
- 【VSA】One-shot video-based person re-identification with variance subsampling algorithmIDEGo
- HDU 5816 Hearthstone(狀態壓縮DP+概率)
- 思維題專項訓練
- 提高組雜題訓練1
- 定積分例題訓練
- 換元積分法訓練題
- 概率論與數理統計 19
- 【演算法學習筆記】概率與期望DP演算法筆記
- 洛谷 P4284 [SHOI2014]概率充電器 概率與期望+換根DP
- 19_04_02校內訓練[特殊的行列式]
- Xbox Game Pass Ultimate 14 Day Trial Recurs Monthly All In OneGAM
- An important personImport
- 面試概率題面試
- bzoj 4899 記憶的輪廓 題解(概率dp+決策單調性優化)優化
- 【學校訓練記錄】10月個人訓練賽3個人題解
- 2024.10.2 總結(集訓;DP)