1. 程式人生 > >【SOJ 754】遊戲

【SOJ 754】遊戲

【題目】

題目描述:

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

輸入格式:

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

輸出格式:

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

樣例資料:

輸入 1

輸出 0.666667

備註:

【資料範圍】 對於 30%30\% 的資料,nn1010 對於 100%100\% 的資料,nn500500

【分析】

概率 dpdp 入門題

定義 fi,jf_{i,j} 表示 Alice 得了 ii 分,Bob 得了 jj 分後 Alice 獲勝的概率

那麼初始化 fn,i=1f_{n,i}=100 ii nn),最後的答案 ansans 會在 f0,0f_{0,0}

現在就考慮如何通過後面的概率來轉移 fi,jf_{i,j}

我們列舉 Alice 下一步的得分(由於 Bob

只有 0011 兩種分值,不用列舉)

如果下一步的任務難度為 pp,令 k=2p1k=2^{p-1},那麼拿到這 kk 分的概率就是 12p\frac{1}{2^p}(即 12k\frac{1}{2\cdot k}),不得分的概率是 2k12k\frac{2\cdot k-1}{2\cdot k}

那麼轉移方程就是:fi,j=fi+k,j4k+fi+k,j+14k+fi,j(2k1)4k+fi,j+1(2k1)4kf_{i,j}=\frac{f_{i+k,j}}{4k}+\frac{f_{i+k,j+1}}{4k}+\frac{f_{i,j}\cdot(2k-1)}{4k}+\frac{f_{i,j+1}\cdot (2k-1)}{4k}

把右邊的 fi,jf_{i,j} 移到左邊來的話,就是 fi,j=(fi+k,j)+(fi+k,j+1)+(fi,j+1(2k1))2k+1f_{i,j}=\frac{(f_{i+k,j})+(f_{i+k,j+1})+({f_{i,j+1}\cdot (2k-1)})}{2k+1}

應該還是比較好懂的吧

【程式碼】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 505
using namespace std;
double f[N][N];
int main()
{
	int n,i,j,k;
	scanf("%d",&n);
	for(i=0;i<=n;++i)
	  f[n][i]=1;
	for(i=n-1;i>=0;--i)
	  for(j=n-1;j>=0;--j)
	    for(k=1;k/2<=n;k<<=1)
	    {
	    	int next=min(i+k,n);
	    	f[i][j]=max(f[i][j],(f[next][j]+f[next][j+1]+f[i][j+1]*(2*k-1))/(2.0*k+1.0));
	    }
	printf("%.6lf",f[0][0]);
	return 0;
}