题意: 在一张飞行棋地图上,你刚开始在0点,终点是n点,你每次可以摇一个骰子,等概率前进1~6步,当你走到或者超过点n,即胜利。图中有m条通道,即当你在x[i]时,免费通向y[i]点。现在让你计算:你要获得胜利,期望摇骰子的次数是多少?
思路: 设f[i]为走到i点,还需要摇f[i]次骰子。直接从后6步分别转移就行了。注意有免费通道的时候,走免费通道肯定是更好的,那么我们直接从通道结束的地方向通道开始的地方转移就行。
代码:
#include<bits/stdc++.h>
#include<cstring>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define lowbit(x) x&-x
#define pii pair<int,int>
#define ull unsigned long long
#define pdd pair<double,double>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
int x=0,f=1;
char ch=gc();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=gc();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=gc();
}
return x*f;
}
using namespace std;
const int N=1e5+666;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-7;
const double PI=acos(-1);
int b[N];
double f[N];
int solve()
{
int n,m;
double p = 1.0/6.0;
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
memset(b,-1,sizeof b);
for(int i=1; i<=m; i++)
{
int x,y;
cin>>x>>y;
b[x]=y;
}
memset(f,0,sizeof f);
for(int i=n-1; i>=0; i--)
{
if(b[i]!=-1)
{
f[i]=f[b[i]];
}
else
{
f[i]=0.0;
for(int j=i+1; j<=i+6; j++)
{
f[i] += p*f[j];
}
f[i]+=1.0;
}
}
printf("%.4f\n",f[0]);
}
}
signed main()
{
// int _;
// cin>>_;
// while(_--)
solve();
return 0;
}