51nod3436 Help Shrek and Donkey

3436 Help Shrek and Donkey

有n+m+1张牌,牌上的数字互不相同且均在[1,n+m+1]中。A有n张牌,B有m张牌,还有一张牌盖在桌上。现在A和B轮流操作,他们两个人都足够聪明,A先进行操作,当前操作的那一方有两种操作:
1. 猜盖在桌上的牌是什么,若猜对则直接获胜,猜错则直接输。
2. 猜一张对方的手牌,若猜对则对方需要把该牌扔掉,猜错则没有影响。
假设双方都绝顶聪明,问先手获胜的概率是多少。

n,m≤1000

输入

一行两个整数m,n(0≤m,n≤1000)

输出

一行两个整数表示A和B的胜率,保留到两位整数

输入样例

输入样例1:
0 3
输入样例2:
1 0

输出样例

输出样例1:
0.25 0.75
输出样例2:
1.00 0.00

解析:

这题难就难在先手有“欺骗”操作,也就是说,先手可以选择猜一张我手中的手牌,若后手认为先手在“欺骗”,则先手会丢失一张手牌;反之后手则会认为这张牌就是盖在桌上的那张,然后直接G。
首先注意到若无法确定桌上的牌,则先手必然不会去猜桌上的牌。
如果我们把猜对方的手牌称为“指定”,那么这时先手就只剩下两种操作,分别是“欺骗”和“指定”。后手也存在两种决策,分别是相信和不相信。
若先手选择“欺骗”,后手选择“相信”,收益为1;
若先手选择“欺骗”,后手选择“不相信”,收益为1-f(m,n-1)
若先手选择“指定”,后手选择“相信”,收益为\frac{m}{m+1}(1-f(m-1,n))
若先手选择“指定”,后手选择“不相信”,收益为\frac{m}{m+1}(1-f(m-1,n))+\frac{1}{m+1}
我们设先手选择“指定”的概率为p
那么后手选择“相信”时先手获胜概率为(1-p)+\frac{m}{m+1}(1-f(m-1,n))p
同理后手选择“不相信”时先手获胜的概率为(1-f(m,n-1))(1-p)+(\frac{m}{m+1}(1-f(m-1,n))+\frac{1}{m+1})p
由于后手需要让先手获胜的概率尽量小,所以先手获胜的概率就是两者之中的较小值。而先手又要选择一个p好让自己获胜的概率尽量大。
注意到这是两条直线,且一条斜率大于0另一条斜率小于0,那么显然二者的交点即为答案。
时间复杂度O(n^{2})

放代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int N=1e3+7;
bool vis[N][N];
double f[N][N];
inline double dp(int n,int m){
	if(vis[n][m])return f[n][m];
	vis[n][m]=true;
	if(n==0)return f[0][m]=1./(m+1.);
	if(m==0)return f[n][0]=1;
	double t1=dp(m,n-1),t2=dp(m-1,n);
	double p=t1/(t1+1./(m+1));
	return f[n][m]=p*m/(m+1)*(1-t2)+1-p;
}
signed main(){
	int n,m;
	scanf("%d%d",&n,&m);dp(n,m);
	printf("%.2f %.2f",f[n][m],1-f[n][m]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ZCH1901/article/details/120557267