XJOI 3870 游戏的期望

题意

有一个游戏平板上面有\(n* m\)个格子,一开始每个格子都是关闭的,每个格子里面都有一个标记
已知每种标记恰好出现两次,也就是一共有\(n∗ m/2\)种标记
规定一次移动为依次(one by one不是同时)打开一对格子查看里面的标记,如果标记不一样,格子会自动关闭,但是你的记忆是超强了,看过了就不会忘,如果标记是一样的,格子从此就一直保持打开状态,当所有格子都打开时游戏结束
请算出游戏结束的最少期望步数

输入格式

输入一行包含两个整数\(N,M (1≤N≤50,1≤M≤50)\)
\(N∗ M\)是偶数

输出格式
输出一个浮点数.误差不超过\(1e−9\)

样例1

1 2

1.0

样例2

2 2

2.6666666666666665

样例3

2 3

4.333333333333334

样例4

4 4

12.392984792984793

分析

这是一道期望dp(概率dp)题。
\(dp[i][j]\) 表示还有 \(i+j\) 张牌未匹配,已翻开 \(i\) 张,未翻开 \(j\) 张。

状态转移分类讨论:

从剩下 \(j\) 张牌中选择一张 \(A\)

1.恰好与已翻开的i张中的一张 \(B\) 匹配,则翻开 \(B\)

2.未与已翻开的匹配,则再随机翻一张 \(B\)

(1) \(A,B\) 刚好匹配;

(2) \(A,B\)不匹配,也没有与已翻开的匹配;

(3) \(B\) 与已翻开的 \(i\) 张中的一张 \(C\) 匹配,则在下一轮中翻开 \(B,C\)

转移方程:

\(p\) 为1.情况的概率, \(b\) 为2.(1)情况概率, \(c\) 为2.(2)情况概率, \(d\) 为2.(3)情况概率,有\[dp[i][j]=p*(1+dp[i-1][j-1])+(1-p)*(b*(1+dp[i][j-2])+c*(1+dp[i+2][j-2])+d*(2+dp[i][j-2]))\]

另外,注意精度问题

Code

#include<cstdio>
#define maxn 2502
using namespace std;
double dp[maxn][maxn];
//期望dp是倒推的
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    n*=m;
    for(int j=0;j<=n;j++){
        for(int i=0;i<=n;i++){
            if((!i&&!j)||(i>j)||(i+j>n)||((j-i)&1))continue;
            double p=double(i)/j;
//p:从剩下j张未翻开的牌中选择一张A,恰好与已翻开的i张中的一张B匹配,则翻开B
            if(j&&i){
                dp[i][j]+=p*(1+dp[i-1][j-1]);
            }
            if(j>=2){
                double b=1./(j-1),c=double(j-i-2)/(j-1),d=1-b-c;
//b:从剩下j张未翻开的牌中选择一张A,未匹配,再随机翻一张B,A,B刚好匹配
//c:从剩下j张未翻开的牌中选择一张A,未匹配,再随机翻一张B,无任何匹配
//d:从剩下j张未翻开的牌中选择一张A,未匹配,再随机翻一张B,B与已翻开的i张中的一张C匹配,则在下一轮中翻开B,C 
                dp[i][j]+=(1-p)*(b*(1+dp[i][j-2])+c*(1+dp[i+2][j-2])+d*(2+dp[i][j-2]));
            }
        }
    }
    printf("%.11lf",dp[0][n]);
    return 0;
}

转载于:https://www.cnblogs.com/BlogOfchc1234567890/p/9865589.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值