题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4405
题意:一个人在玩飞行棋,一共有n个点和m条航线,每一条航线有x,y,如果到达点x那么会直接到达点y(x<y),初始在1,当坐标大于等于n时游戏结束。每一步会投一个六面骰子来决定移动步数,求游戏结束的期望投掷次数。
思路:f[i]表示在i点时游戏结束的期望次数。f[i] = 1 / 6( ∑f[i+j] ) + 1 (1<=j<=6) 或者 f[i] = f[ pos[i] ] i->pos[i]是一条航线。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define rep(i,j,k) for(int i=j; i<=k; i++)
#define Clean(x,y) memset(x,y,sizeof(x))
const int maxn=100009;
int aim[maxn];
bool flag[maxn];
double f[maxn];
int n,m;
int main()
{
while(cin>>n>>m)
{
if(m+n==0) break;
Clean(f,0);
Clean(flag,false);
Clean(aim,0);
int x,y;
rep(i,1,m)
{
scanf("%d %d",&x,&y);
flag[x]=true;
aim[x]=y;
}
rep(i,1,n)
{
int temp=aim[i];
while(aim[temp]) temp=aim[temp];
aim[i]=temp;
}
f[n]=0;
for(int i=n-1;i>=0;i--)
{
if (flag[i]) f[i] = f[ aim[i] ];
else f[i]=(f[i+1]+f[i+2]+f[i+3]+f[i+4]+f[i+5]+f[i+6])/6+1;
}
printf("%0.4f\n",f[0]);
}
return 0;
}