zoukankan      html  css  js  c++  java
  • JZOJ6026. 【GDOI2019模拟2019.2.23】飞行棋

    Description

    在这里插入图片描述

    Data Constraint

    在这里插入图片描述

    Solution

    • 由于数据的特殊性以及精度的局限性,我们可以考虑暴力枚举轮数,然后计算答案,这样的轮数是在可以接受的范围内的。
    • 设状态f[i][j]表示第i轮,从j出发到达终点的概率,这个十分好转移O(6n)。
    • 对于第i轮,棋子x获胜的概率,是前i-1轮没有结束游戏,且前x-1个棋子也没有到达终点时,自己到达了终点。
    • 设b[i]表示棋子i的到达终点的概率(在当前i轮后)。记一个后缀积s[i]表示上一轮的1-b[j](i<=j<=m)的积,再乘上前缀积t[i]表示这一轮的1-b[j](1<=j<=i)的积
    • 贡献就是s[i+1]* t[i-1] *这个棋子前几轮没有到终点 * b[i]。O(m)。
    • O(K*(6n+m))
    • 当游戏继续的概率小于某个阈值时就可以停了。
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define eof 0.0000001
    #define K 100000
    #define maxn 160
    #define maxm 21
    #define db long double 
    using namespace std;
    
    int n,m,i,j,k,a[maxn],w[maxm];
    db f[2][maxn],b[maxm],s[maxm],d,rem,sum,ans[maxm];
    
    int main(){
    	freopen("feixingqi.in","r",stdin);
    	freopen("feixingqi.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++) scanf("%d",&a[i]);
    	for(i=1;i<=m;i++) scanf("%d",&w[i]);
    	if (m==1){
    		printf("1.000000");
    		return 0;
    	}
    	
    	memset(b,0,sizeof(b));
    	for(i=0;i<6;i++) f[0][n+i]=1;
    	sum=1; int t=0; d=1./6;
    	for(;sum-eof>0;){
    		t++;
    		int p=t&1,q=p^1;
    		memset(f[p],0,sizeof(f[p]));
    		for(i=1;i<n;i++) if (a[i]==i) for(j=1;j<=6;j++) 
    			f[p][i]+=d*f[q][i+j];
    		for(i=1;i<=n;i++) f[p][i]=f[p][a[i]];
    		s[m+1]=1;
    		for(i=m;i>=1;i--) s[i]=s[i+1]*(1-b[i]);
    		sum=1;
    		for(i=1;i<=m;i++) {
    			ans[i]+=sum*s[i+1]*f[p][w[i]];
    			b[i]=b[i]+f[p][w[i]];
    			sum=sum*(1-b[i]);
    		}
    	}
    	for(i=1;i<=m;i++) printf("%.6Lf
    ",ans[i]);
    }
    
  • 相关阅读:
    php RSA公钥私钥加解密和验证用法
    php格式化RSA公钥私钥字符串
    你的周末时光是什么样的?
    php-redis 消息订阅笔记
    php redis 常用操作
    MySql索引笔记
    yii1框架,事务使用方法
    python 项目打包成exe可执行程序
    Linux修改默认端口
    C++字符串作为参数的传递
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700948.html
Copyright © 2011-2022 走看看