Landlords

题目大意

先手有n张牌,后手有m张牌,桌面上还有一张牌。n+m+1张牌互不相同且双方都知晓自己的牌是什么。
两人轮流操作,操作类型有二:
1、说桌面上的牌是什么,说对胜利,说错失败,执行此操作后游戏结束。
2、说一张牌,如果对方手里有则展示并弃置。
求先后手获胜概率。

神奇的概率题

我们来考虑一下第二个操作,我们可以选择
1、老老实实去试探对方的牌,称之为我是正昊
2、耍小聪明欺骗对方,报一张自己的牌,称之为我是水栓
这是我们的决策,对方也有决策,即认为我是正昊还是水栓。
设f(n,m)表示先手有n张牌后手有m张牌先手获胜的概率。
可以列个表
这里写图片描述
假设我们有p的概率成为正昊,1-p的概率成为水栓,那么对方因为要降低我们的收益,会在两种决策中选择较小的,因此获胜概率为min(p*m/(m+1)[1-f(m,n-1)]+1-p,p*m/(m+1)[1-f(m,n-1)]+p/(m+1)+1-p-(1-p)*f(m,n-1))
p是自变量,随手玩一玩发现他们是两条直线,一条斜率为正一条斜率为负。
我们的极值肯定取在他们的交点,对于f我们递归计算,然后接着解出p,就可以算出f(n,m)。
注意n*m=0就到边界了。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef double db;
int i,j,k,l,t,n,m;
bool bz[1200][1200];
db f[1200][1200];
void dfs(int n,int m){
    if (bz[n][m]) return;
    bz[n][m]=1;
    if (n*m==0) f[n][m]=(db)1/(m+1);
    else{
        dfs(m-1,n);
        dfs(m,n-1);
        db a=f[m-1][n],b=f[m][n-1];
        db p=(db)b*(m+1)/(b*(m+1)+1);
        f[n][m]=(db)p*m/(m+1)*(1-a)+1-p;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    dfs(n,m);
    printf("%.6lf %.6lf\n",f[n][m],1-f[n][m]);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值