zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    HLG 1522 子序列的和【队列的应用】
    POJ 3273 Monthly Expense【二分】
    HDU 4004 The Frog's Games 【二分】
    POJ 2001 Shortest Prefixes【第一棵字典树】
    POJ 2823 Sliding Window【单调对列经典题目】
    HDU 1969 Pie 【二分】
    POJ 3125 Printer Queue【暴力模拟】
    POJ 3250 Bad Hair Day【单调栈】
    字典树【模板】
    验证码 Code
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10416064.html
Copyright © 2011-2022 走看看