CF-98E
题意
A 有 n 张牌, B 有 m 张牌,桌上还有一张反扣着的牌,牌的编号在 [1,n+m+1] 之间且互不相同。
用这些牌进行博弈,每轮每人可以进行如下操作中的一个:
- 猜桌面上的反扣着的牌上的数字,猜对则获得胜利,猜错则对方胜利。
- 询问对方是否有某张牌,若拥有则对方需要出示这张牌,否则继续游戏。
若 A 和 B 都绝顶聪明,求 A 的胜率。 n,m≤1000
题解
“首先我们清楚的知道双方的策略必然包含随机因素,因为这是一个非完全信息博弈,同时由于这是一个零和博弈,双方的策略都希望能够最小化对方获胜的概率。那么模型就很清楚了,混合策略纳什均衡。” ——搬自zxyoi
dpn,m 表先手 n 张牌,后手 m 张牌,先手胜的概率,我胜即你输,显然 dpn,m=1−dpm,n
然后边界显然:
- dpn,0=1 先手知道桌上牌,必胜
- dp0,m=m+11 先手无牌,只能盲猜
对于 dpn,m 其他转移,首先不会轻易猜桌上的牌。
对于询问,先手可以“欺骗”或“猜测”,后手可以认为先手 欺骗/猜测
“欺骗”便是先手询问自己的牌,对手肯定没有,以此误导对手猜桌上的牌。“猜测”自然是询问不是自己的牌,大概率能排除对手的牌
分类讨论:
- A. 先手欺骗,后手认为欺骗,相当于后手知道了先手一张牌
A=1−dpm,n−1
- B. 先手欺骗,后手认为猜测。后手会认为这就是桌上的牌,于是先手必胜
B=1
- C. 先手猜测,后手认为猜测。m+1m 概率后手有,后手牌减一继续,m+11 概率后手无(后手知道桌上牌),先手输
C=m+1m×(1−dpm−1,n)
- D. 先手猜测,后手认为欺骗,m+1m 概率后手有,同 C,m+11 概率后手无,后手不会选,先手能赢
m+1m×(1−dpm−1,n)+m+11
先手\后手 |
欺骗 |
猜测 |
欺骗 |
A |
B |
猜测 |
D |
C |
设先手欺骗概率为 p ,根据纳什均衡, (后手欺骗猜测时先手获胜期望要相同)
Ap+D(1−p)=Bp+C(1−p)p=(C−D)/(A−D−B+C)
再把 p 带回,
dpn,m=Ap+D(1−p)
CODE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <bits/stdc++.h> using namespace std; template<typename T> inline void red(T &x) { x=0;bool fg=0;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') fg^=1;ch=getchar();} while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(T)(ch^48),ch=getchar(); if(fg) x=-x; } const int N = 1005; int n,m; double dp[N][N]; double DFS(int n,int m) { if(dp[n][m]>=0) return dp[n][m]; if(n==0) return dp[n][m]=1.0/(m+1); if(m==0) return dp[n][m]=1.0; double A=1.0-DFS(m,n-1),B=1.0,C=1.0*m/(m+1.0)*(1.0-DFS(m-1,n)),D=C+1.0/(m+1.0); double p=(C-D)/(A-D-B+C); return dp[n][m]=A*p+(1.0-p)*D; } int main() { cin>>n>>m; for(int i=0;i<=max(n,m);i++)for(int j=0;j<=max(n,m);j++) dp[i][j]=-1; printf("%.9lf %.9lf\n",DFS(n,m),1.0-DFS(n,m)); return 0; }
|