zoukankan      html  css  js  c++  java
  • 【NOIP2012模拟10.31】掷骰子

    题目

    太郎和一只免子正在玩一个掷骰子游戏。有一个有N个格子的长条棋盘,太郎和兔子轮流掷一个有M面的骰子,骰子M面分别是1到M的数字.且掷到任意一面的概率是相同的.掷到几.就往前走几步.当谁走到第N格时,谁就获胜了。游戏中还有一个规则“反弹”.就是当一位选手要走到第N格外时.他就会后退(就像飞行棋进营一样)。

    假设现在一位追手在A格.当他掷出B时:
    
    
    1.A+B<N,走到第A+B.络,
    
    
    2.A+B=N,走到第N格,获胜。
    
    
    3.A+B≥N,走到第(N-(A+B-N)格
    
    
    现在太郎和兔子分别在第x和y格.接下来是太郎掷骰子,太郎想知道他赢得比赛的概率就多少。
    

    分析

    (f_{i,j})表示太郎在i,兔子在j,太郎的胜率。我们从后往前转移。
    我们分四种情况:

    1、i+m<=n and j+m<=n
    2、i+m>n and j+m<=n
    3、i+m<=n and j+m>n
    4、i+m>n and j+m>n
    

    why?
    因为发现,当(i+m>n)时,i怎么跳总是(i+m>n),那么就可以把它们当做同一种状态。j也一样。

    情况一:i+m<=n and j+m<=n

    因为i走到k的概率为(dfrac{1}{m}),j走到l的概率也为(dfrac{1}{m})
    那么状态(i,j)的胜率就是状态(k,l)胜率的总和。

    [f_{i,j}=dfrac{1}{m^2}sum_{k=i+1}^{i+m+1}sum_{l=j+1}^{j+m+1}f_{k,l} ]

    情况二:i+m>n and j+m<=n

    [f_{i,j}=dfrac{(m-1)sum_{l=j+1}^{j+m+1}f_{i,l}}{m^2}+dfrac{1}{m} ]

    显然i有(dfrac{1}{m})的概率到达终点,而i有m种可能,又那么既然已经算了到达终点的概率,那么就不用在计算,所以乘以(m-1)。

    情况三:i+m<=n and j+m>n

    [f_{i,j}=dfrac{(m-1)sum_{k=i+1}^{i+m+1}f_{k,j}}{m^2}+dfrac{x(如果i=n-m,x=1,否则x=0)}{m} ]

    同样j有m种可能,但不能让他到达终点,那么就不用在计算,所以乘以(m-1)。
    而当i在n-m这个位置时,i也有(dfrac{1}{m})的概率到达终点,有可能出现状态(n,n),由于太郎是先手,所以算太郎赢,而前面有减去了j到达终点的情况,所以加上去。

    情况四:i+m>n and j+m>n

    要求i赢,所以
    当i第一回合就走到了n,概率为(dfrac{1}{m})
    当i第一回合没有走到n,而j也不能走到n,在第二回合i走到了n概率为(dfrac{1}{m}(1-dfrac{1}{m})^2)
    如果在第二回合i还是没有走到n,而j还是不能走到n,在第三回合i走到了n概率为(dfrac{1}{m}(1-dfrac{1}{m})^4)
    如此类推,

    [f_{i,j}=limit_{n oinfty}dfrac{1}{m}+dfrac{1}{m}(1-dfrac{1}{m})^2+dfrac{1}{m}(1-dfrac{1}{m})^4+...+dfrac{1}{m}(1-dfrac{1}{m})^{2n} ]

    [=dfrac{1}{m}(1+(1-dfrac{1}{m})^2+(1-dfrac{1}{m})^4+...)+(1-dfrac{1}{m})^{2n} ]

    等比数列求和

    [=dfrac{1}{m}dfrac{1*[1-(1-dfrac{1}{m})^{2n}]}{1-(1-dfrac{1}{m})^2} ]

    因为数列的公比小于1,([1-(1-dfrac{1}{m})^{2n}])无限趋近于1,所以

    [=dfrac{1}{m}dfrac{1}{1-(1-dfrac{1}{m})^2} ]

    解得

    [f_{i,j}=dfrac{m}{2m-1} ]

    但是这样是(O(n^4))的,用矩阵后缀和优化,变成(O(n^2))

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=2005;
    using namespace std;
    double f[N][N],n,m,x,y;
    double val(int x1,int y1,int x2,int y2)
    {
    	return f[x1][y1]-f[x1][y2]-f[x2][y1]+f[x2][y2];
    }
    int main()
    {
    	scanf("%lf%lf%lf%lf",&n,&m,&x,&y);
    	for(int i=n;i>=1;i--)
    		for(int j=n;j>=1;j--)
    		{
    			f[i][j]=f[i+1][j]+f[i][j+1]-f[i+1][j+1];
    			if(i==n)
    			{
    				f[i][j]++;
    				continue;
    			}
    			if(j==n) continue;
    			if(i+m>n && j+m>n)
    				f[i][j]+=m/(2*m-1);
    			else
    			if(i+m>n)
    				f[i][j]+=val(i,j+1,i+1,j+m+1)*(m-1)/m/m+1/m;
    			else
    			if(j+m>n)
    				f[i][j]+=(m-1)*val(i+1,j,i+1+m,j+1)/m/m+(i==n-m)/m/m;
    			else
    				f[i][j]+=val(i+1,j+1,i+m+1,j+m+1)/(m*m);
    			
    		}
    	printf("%.6lf",val(x,y,x+1,y+1));
    }
    
    
  • 相关阅读:
    Spring AOP 代理创建方式
    VS全局搜索
    uni-app中添加AES加密
    中国菜刀"连接被重置"问题解决
    Windows go get下载包失败问题解决
    搭建vulhub 漏洞环境及安装Docker和docker-compose
    DedeCMS 5.7通用重装漏洞分析
    各就各位,预备,GO!
    ARL资产灯塔系统分组资产导出脚本
    玩《巫师3》需要了解的背景知识
  • 原文地址:https://www.cnblogs.com/chen1352/p/9045311.html
Copyright © 2011-2022 走看看