【Codeforces 98E】 Help Shrek and Donkey

http://codeforces.com/problemset/problem/98/E (題目連接)ios

題意

  A君有n張牌,B君有m張牌,桌上還有一張反扣着的牌,每張牌都不同。spa

  每一個回合能夠作兩件事中的一件.net

  • 猜想桌上的牌是什麼,猜對則勝,猜敗則輸。
  • 詢問對方是否有某張牌,如有則須要將其示出,不然繼續遊戲。

  A和B都很聰明,問A的勝率。code

Solution

  碉堡了!!轉自:http://blog.csdn.net/Yves___/article/details/51814024blog

  首先不到最後一刻是不會選擇猜桌上的牌的。遊戲

  假如某一次對方問了一張本身手上沒有的牌,就可能會懷疑桌上的牌就是這張。get

  而詢問對方是否有某張牌,咱們能夠選擇詢問本身手上有的牌,假如對方相信而去猜想這張牌的話就會輸掉,咱們稱這樣的行爲做欺騙。string

  記$f(n,m)$表示先手有$n$張牌,後手有$m$張牌,先手的獲勝機率。it

  那麼就能夠列一個表格,表示先手的選擇以及後手的應對。io

  • 先手選擇猜想對方的牌

    • 後手認爲先手在猜想,先手獲勝的機率是$\displaystyle\frac{m}{m+1}(1-f(m-1,n))$
    • 後手認爲先手在欺騙,先手獲勝的機率是$\displaystyle\frac{1}{ m+1 } + \frac{m}{m+1}(1-f(m-1,n))$
  • 先手選擇欺騙

    • 後手認爲先手在猜想,先手獲勝的機率是$\displaystyle 1$
    • 後手認爲先手在欺騙,先手獲勝的機率是$\displaystyle 1-f(m,n-1)$

  那麼對於先手的任意一個策略,後手會選擇最優的策略去使他贏的機率儘量小。也就是說假如先手用$p$的機率選擇去猜想,$1−p$的機率選擇去欺騙。那麼最終的貢獻就是

$$\max\limits_p \left\{ \min \left\{ \frac{pm}{m+1}( 1-f( m-1, n ) )+(1-p), \frac{p}{ m+1 } + \frac{pm}{ m+1 }( 1-f( m-1, n )) + (1-p)(1-f( m, n-1)) \right\} \right\}$$

  將$p$視爲自變量,問題就轉化爲兩條直線取$min$的問題,求個交點就能夠獲得最大值。

細節

  直線的交點別求錯了。。

代碼

// codeforces 98E
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

double g[1010][1010];

double f(int n,int m) {
	if (!n) return 1.0/(m+1);
	if (!m) return 1.0;
	if (g[n][m]) return g[n][m];
	double A=(1-f(m-1,n))*m/(m+1);
	double B=(1-f(m-1,n))*m/(m+1)+1.0/(m+1);
	double C=1.0;
	double D=1-f(m,n-1);
	double p=(D-C)/((A-C)-(B-D));
	return g[n][m]=p*A+(1-p)*C;
}
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	printf("%.10lf %.10lf",f(n,m),1-f(n,m));
	return 0;
}
相關文章
相關標籤/搜索