• dtoj#4120. 飞行棋(feixingqi)


    题目描述:

    小G在玩飞行棋。这个飞行棋与一般的飞行棋相比,规则要简单得多。棋盘上一共有从左到右$n$个格子,按$1$到$n$标号。$m$个玩家各持有一个棋子。棋子第一个到达第$n$格的玩家胜利。每个玩家轮流投掷$6$面的骰子,投出几点就把自己的棋子往右移动几步。当棋子被移动到某些格子时,棋子会被传送到其他格子。如果棋子被移动到第$i$格,若$a_i=i$,则棋子仍然在第$i$格;否则棋子会被传送到第$a_i$格。棋子每次按骰子投出的数字移动时,是一次性移动了若干格,即棋子不会在中途被传送走,只可能在移动完后被传送走。不同玩家的棋子之间互不影响。

    现在小G告诉了你$m$个玩家棋子所在位置。现在开始按$1$号玩家到$m$号玩家的顺序依次扔骰子。小G想知道每个玩家获胜的概率。

    算法标签:DP

    思路:

    因为其具有收敛性,所以当你局数足够多时,近似于得到答案。

    令状态表示 $f[i][j]$ 表示初始位置在 $j$ 经过 $i$ 局恰好到 $n$ 的概率。依此枚举在某一轮我成功了其余都在我之后成功过的概率,得到答案。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define db double
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const db P=1.0/6.0;
    const int N=170,M=550000;
    int n,m,a[N],p[22],op;
    db f[2][N],g1[M+2][22],g2[M+2][22],g[M+2][22];
    il int read(){
       int x,f=1;char ch;
       _(!)ch=='-'?f=-1:f;x=ch^48;
       _()x=(x<<1)+(x<<3)+(ch^48);
       return f*x;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=n+1;i<=n+6;i++)a[i]=n;
        for(int i=1;i<=m;i++)p[i]=read();
        if(m==1){puts("1.000000");return 0;}
        f[0][n]=1.0;
        for(int i=1;i<=M;i++){
            op^=1;
            for(int j=1;j<=n;j++)f[op][j]=0;
            for(int j=1;j<n;j++){
                for(int k=1;k<=6;k++)
                    f[op][j]+=f[op^1][a[j+k]]*P;
            }
            for(int j=1;j<=m;j++)g[i][j]+=f[op][p[j]];
            
        }
        for(int i=M;i;i--)for(int j=1;j<=m;j++)g[i][j]+=g[i+1][j];
        for(int i=1;i<=M;i++){
            g1[i][0]=g2[i][m+1]=1.0;
            for(int j=1;j<=m;j++)g1[i][j]=g1[i][j-1]*g[i][j];
            for(int j=m;j;j--)g2[i][j]=g2[i][j+1]*g[i][j];
        }
        for(int i=1;i<=m;i++){
            db ans=0;
            for(int j=1;j<=M;j++){
                ans+=g1[j+1][i-1]*g2[j][i+1]*(g[j][i]-g[j+1][i]);
            }
            printf("%lf
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    快速查看表结构(zml)
    康尼机电的发送邮件的功能2
    康尼机电的发送邮件的功能1
    8.2文件控制总览只循环了第一行
    ClientScript.RegisterStartupScript
    康尼机电的委托协议中的点击操作显示标签卡的功能
    1020 Tree Traversals (25 分)
    1017 Queueing at Bank (我自己写的模拟时间的版本)
    1016 Phone Bills ( vector的使用)
    1015 Reversible Primes
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10416064.html
Copyright © 2020-2023  润新知