【hdu4405】Aeroplane chess

题目描述

有编号为0-n的格子,从0开始,扔骰子扔到几就走几格。有m个瞬移点,每个点可以从格x直接飞到格y,若瞬移到另一个瞬移点可以继续瞬移。求到达格n的期望扔骰子次数。
输入

有多组数据。每组数据第一行两个数n,m,记下来m行,每行两个数x,y,表示可以从格x直接飞到y。以 0 0 作为结尾。
输出

对于每组数据输出一个数,表示期望次数,保留4位小数。
样例输入

2 0
8 3
2 4
4 5
7 8
0 0


样例输出

1.1667
2.3441


题解

期望dp的一般解法。设 dp[ i ] 为从第 i 个格子到第 n 个格子的期望次数,

如果当前格子 i 无法直接飞到另一个格子 ,那么 dp[ i ] = ( dp[ i+1 ] + dp[ i+2 ] + dp[ i+3 ] + dp[ i+4 ] + dp[ i+5 ] + dp[ i+6 ]) / 6 + 1 ;

如果 i 可以直接飞到 j,则 dp[ i ] = dp[ j ] ;

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=100000+50;

int n,m,x,y,nex[maxn];
double dp[maxn];

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    while(cin>>n>>m&&(n||m)){
        memset(pre,0,sizeof(pre));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++){
            read(x),read(y);
            nex[x]=y;
        }
        for(int i=n-1;i>=0;i--){
            if(!pre[i]) dp[i]=(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])/6.0 + 1 ;
            else dp[i]=dp[nex[i]];
        }
        printf("%.4lf
",dp[0]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/rlddd/p/9489386.html