dtoj#4120. 飞行棋(feixingqi)

题目描述:

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

现在小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\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Jessie-/p/10416064.html

时间: 2024-10-01 00:31:25

dtoj#4120. 飞行棋(feixingqi)的相关文章

纠正飞行棋的错误

错误1:在运行暂停功能时,这个暂停功能可以实现,但无法显示提示信息. 改正如下: case 3: Console.Clear(); Program.drawmap(); isstop[0] = true; Console .WriteLine ("{0}走到了暂停,暂停一次!", name[0]); Console.WriteLine("按任意键继续...");  Console.ReadKey(true); 原因:缺少Console.WriteLine("

骑士飞行棋第三版(上色)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 骑士飞行棋 8 { 9 class Program 10 { 11 12 //在下面的数组存储我们游戏地图各个关卡 13 //数组的小标为0的元素对应地图上的第一格 下标为1的元素对应第二格...下标为n的元素对应n+1

飞行棋2.0--输完姓名后全自动,可修改为人机交互模式

1 // 2 // main.m 3 4 #import <Foundation/Foundation.h> 5 #import "GameController.h" 6 int main(int argc, const char * argv[]) 7 { 8 GameController *ctl = [GameController new]; 9 [ctl startGame]; 10 11 // GameMap *map = [GameMap new]; 12 //

局域网多人对战飞行棋的实现

在项目之间有段“空项期”,上个项目刚刚完成,下个项目还没落实,时间比较充裕.去年9月份就经历了这么一次短暂的“空项期”,那时偶还是一名前端工作者,C#使用起来毫不含糊,还自己整过一个类SCSF的MVP框架AngelFrame(详见之前博客:http://www.cnblogs.com/wgp13x/p/99c2adc52d8f0dff30a038841ac32872.html).在那段“空项期”之前,有位朋友托我做个小游戏,偶也满口的答应,只可惜之前项目太忙没时间做,就一直耽搁了,正好有这段“空

骑士飞行棋第二版(已完善)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 骑士飞行棋 8 { 9 class Program 10 { 11 12 //在下面的数组存储我们游戏地图各个关卡 13 //数组的小标为0的元素对应地图上的第一格 下标为1的元素对应第二格...下标为n的元素对应n+1

骑士飞行棋第一版(掷骰子方法分开)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 骑士飞行棋 8 { 9 class Program 10 { 11 12 //在下面的数组存储我们游戏地图各个关卡 13 //数组的小标为0的元素对应地图上的第一格 下标为1的元素对应第二格...下标为n的元素对应n+1

bzoj 1800: [Ahoi2009]fly 飞行棋 暴力

1800: [Ahoi2009]fly 飞行棋 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1800 Description 给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列. 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形. Input 第一行为正整数N,表示点的个数,接下来N行分别为这N个点所分割的各

HDU 4405 飞行棋求到终点时掷筛子的期望--期望dp

题意:飞行棋,掷筛子,但是如果当前的点有特技的话,可以不用掷筛子而是直接跳到一个指定点Yi,求从起点开始到终点时掷筛子的次数的期望. 分析: 期望dp模型,框架:dp[i]从当前状态i到达目标状态需要掷筛子的次数的期望,i能到达的状态要么是Yi(用了特技),要么是i+j(j为掷筛子得到的数字),所以状态方程:dp[i]=dp[Yi]或者dp[i+j]*1/6,记得最后要+1. 初始化:memset(dp,0,sizeof(dp)) 实现:从后往前推,但是是从最后一个的前一个,就是说不是从n,而是

C# 基础之飞行棋

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 飞行棋 { class Program { //地图 //0代表普通方块□ //1代表选择盘◎ //2代表地雷☆ //3代表暂停▲ //4代表通道卍 static int[] map = new int[100]; static int[] playerPos = {0,0 }; static int st