zoukankan      html  css  js  c++  java
  • 游戏(期望)


    这是一个期望的题目,有两种做法。
    一种是比较好想的高斯消元,另一种是思维难度稍微大了一些的数学做法,但是代码很短,时间复杂度也更优秀。
    (高斯消元做法)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 210
    int n,m;
    double a[N][N],p;
    void gauss()
    {
        for (int i=0;i<n+m+1;i++)
        {
            int mx=i;
            for (int j=i+1;j<=n+m+1;j++)
            if (fabs(a[j][i])>fabs(a[mx][i])) mx=j;
            if (i!=mx) swap(a[i],a[mx]);
            for (int j=i+1;j<=n+m+1;j++)
            {
                double t=a[j][i]/a[i][i];
                for (int k=i;k<=n+m+2;k++)
                a[j][k]-=t*a[i][k];
            }
        }
    }
    int main()
    {
        n=read(),m=read();cin>>p;
        a[0][0]=p;a[0][1]=1-p;a[0][0]--;a[0][n+m+2]--;
        for (int i=1;i<n+m;i++)
        a[i][i-1]=p,a[i][i+1]=1-p,a[i][i]--,a[i][n+m+2]--;
        a[n+m][n+m]=1-p;a[n+m][n+m-1]=p;a[n+m][n+m]--,a[n+m][n+m+2]--;
        a[n][n-1]=a[n][n+1]=a[n][n+m+2]=0;
        a[n+m+1][n-1]=p,a[n+m+1][n+1]=1-p,a[n+m+1][n+m+1]--,a[n+m+1][n+m+2]--;
        gauss();
        printf("%.7lf",a[n+m+1][n+m+2]/a[n+m+1][n+m+1]);
        return 0;
    }
    

    以前没有怎么做过期望的题目,更是没有想到可以用高斯消元来做期望的题目。

    但是现在发现其实这是个挺常见的套路,所以就学习了一下qwq

    有兴趣的话可以去做一下HNOI2013游走,这个也是高斯消元来求解未知数的期望类型题目。

    (数学做法)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 110
    using namespace std;
    long double sum[MAXN],p,ans=1.0;
    int n,m;
    int main()
    {
    	cin>>n>>m;
    	cin>>p;
    	sum[0]=1.0;
    	for(int i=1;i<=n+m;i++)
    		sum[i]=sum[i-1]*(1-p)/p,ans+=sum[i];
    	printf("%.8Lf",(1/(sum[n]/ans)));
    	return 0;
    }
    

    其实这个题有类似的题目收集邮票有兴趣的话可以尝试一下,思路很相近。

    这个做法就比较玄妙了。

    我们可以这样想:

    我们把状态进行分离,因为Alice和Bob的宝石总和不变,所以我们只考虑Alice的个数,我们将状态抽离出来为她拥有0~n+m这n+m+1种状态,我们要计算这些状态在总体上的期望出现次数。而这些状态之间每次都会有概率加成的转移。

    因为游戏会进行无限轮(也就是无穷大),这样的话开始几次的情况其实对整体的影响很小很小。而在进行了无穷多的传递后,各个状态出现的期望出现次数应该是达到了稳定值(当然这其中肯定是每轮之间是有变化的,但是要理解的一点是,我们将状态转移进行了无穷多轮,所以我们要从整体上来看,那么均摊到每个状态的概率肯定是稳定的、恒定的)

    既然每种状态的概率是稳定的,那么我们考虑每次状态的转移。考虑状态(A_k)和它的上一个状态(A_{k-1})(A)每次有p的概率转移到上一个状态,它的上一个状态有1-p的概率转移到它。但是要维持在总体上他们的稳定,那么就有(A_k imes p=A_{k-1} imes (1-p)),这样的话我们可以知道这些状态的分布呈公比为(frac{1-p}{p})的等比数列。那么我们假设开始的0状态为单位1,就可以进行递推了。

    随后我们可以用(A_n)状态来除以总数,算出在这些状态中(如果把总和看作单位1的话),n状态出现的次数(比1小)。最后我们将整个游戏的无数个回合具象成一条直线。那么n状态就是上面的一些间隔的点。我们要求的问题也可以转化成相邻两个n状态出现的间隔。那么就用1来除以它就可以了。

  • 相关阅读:
    关于jstl.jar引用问题及解决方法
    React 解析/ 第二节 使用 Reac
    NOde.js的安装和简介
    JACOB调用控件函数
    Linux 常用命令
    webService接口发布失败问题
    CommonsMultipartFile---用Spring实现文件上传
    验证签名(章)是否有效的方法
    新起点,新征程
    使用C#正则表达式获取必应每日图片地址
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9763816.html
Copyright © 2011-2022 走看看