1. 程式人生 > >期望/概率dp

期望/概率dp

題目描述

Alice 和 Bob 兩個人正在玩一個遊戲,遊戲有很多種任務,難度為 p 的任務(p是正整數),有 1/(2^p) 的概率完成並得到 2^(p-1) 分,如果完成不了,得 0 分。一開始每人都是 0 分,從 Alice 開始輪流做任務,她可以選擇任意一個任務來做;而 Bob 只會做難度為 1 的任務。只要其中有一個人達到 n 分,即算作那個人勝利。求 Alice 採取最優策略的情況下獲勝的概率。

輸入格式

一個正整數 n ,含義如題目所述。

輸出格式

一個數,表示 Alice 獲勝的概率,保留 6 位小數。

輸入

1

輸出

0.666667

備註

【資料範圍】 對於 30% 的資料,n≤10 對於 100% 的資料,n≤500

分析

概率dp入門題 定義 f[i][j]f[i][j] 表示Alice有 i 分,Bob有 j 分時,Alice獲勝的最大概率 顯然 f[n][i]=1f[n][i]=1 (i 0,1,2,...,n\subseteq {0,1,2,...,n}) 最後我們要求的就是f[0][0]f[0][0] 怎麼轉移呢? 令2p1=k2^{p-1}=k,我們列舉Alice下一步的得分(因為Bob只有0和1兩種分值) 由題可知,得到這部分分的概率是 12p=12k\frac{1}{2^p}=\frac{1}{2*k}

1 轉移方程就呼之欲出了:

f[i][j]=f[i+k][j]/4k+f[i+k][j+1]/4k+f[i][j+1](2k1)/4k+f[i][j](2k1)/4kf[i][j]=f[i+k][j]/4k+f[i+k][j+1]/4k+f[i][j+1]*(2k-1)/4k+f[i][j]*(2k-1)/4k 除以4k的原因就是有1/2是Bob的,還有1/2*k是Alice的 然後再合併同類項,把右邊的f[i][j]f[i][j]移到左邊,就可以得到

f

[i][j]=(f[i+k][j]+f[i+k][j+1]+f[i][j+1](2k1))/(2k+1)f[i][j]=(f[i+k][j]+f[i+k][j+1]+f[i][j+1]*(2k-1))/(2k+1)

程式碼

#include<bits/stdc++.h>
using namespace std;
int n; 
double f[505][505];
int main()
{
	scanf("%d",&n);
	int i,j,k;
	for(i=0;i<=n;++i) f[n][i]=1;
	for(i=n-1;i>=0;--i)
		for(j=n-1;j>=0;--j){
			double tmp=-1;
			for(k=1;k/2<=n;k<<=1){
				int nxt=min(i+k,n);
				tmp=max(tmp,(f[nxt][j]+f[nxt][j+1]+(2*k-1)*f[i][j+1])/(2*k+1));
			}
			f[i][j]=tmp;
		}
	printf("%.6lf",f[0][0]);
}