题目描述
有编号为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; }