题目大意:给定一张图,A的起始位置和B的启示位置,A在一个时间点内移动两格,B移动一格。且A移动方向始终靠近B,而B等概率的移动到与它联通的节点和所在位置。求当A和B处在同一位置时平均步数为几步。
题目分析:一道求期望的题目。可以先预处理出每个节点向另外节点方向走一步时候的位置。定义状态dp[i][j]表示为B在i,A在j时候的步数期望。
显然对于同一位置即dp[i][i]=0。 如果在一个单位时间内之内可以到达那么期望为1;
设A一开始在j处,一个单位时间内到达Z点,则dp[i][j]=1+(dp[i][Z]+sigma(dp[k][Z]))/(g[i]+1) i与k相连。g[i]表示有几个点与i相连。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
#include<cassert>
#include<climits>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define INF (2139062143)
#define phiF (1000000006)
#define MAXN (1000000+10)
typedef long long LL;
struct info{
int to,next;
}e[2005];
int first[2005],g[2005],dist[2005],tot,n,m,s,en,q[1005],a[1005][1005],x,y;
bool flag[2005];
double dp[1005][1005];
inline void add(int x,int y){
e[++tot].to=y;
e[tot].next=first[x];
first[x]=tot;
++g[x];
}
inline void bfs(int x){
For (i,n)
flag[i]=1,dist[i]=0;
int h=1,t=1;
flag[x]=0;
q[1]=x;
for (;h<=t;h++){
for (int i=first[q[h]];i;i=e[i].next){
int v=e[i].to;
if (flag[v]){
flag[v]=0;
dist[v]=dist[q[h]]+1;
t++;
q[t]=v;
a[v][x]=q[h];
}else if (dist[v]==dist[q[h]]+1 && q[h]<a[v][x]) a[v][x]=q[h];
}
}
}
inline double dfs(int x,int y){
if (dp[x][y]>-1) return dp[x][y];
if (x==y) return dp[x][y]=0;
int z=a[a[x][y]][y];
if (z==y||a[x][y]==y) return dp[x][y]=1;
double tmp=1/(g[y]+1);
double sum=dfs(z,y);
for (int i=first[y];i;i=e[i].next)
sum+=dfs(z,e[i].to);
return dp[x][y]=sum/(g[y]+1)+1;
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&en);
For (i,m) {
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
For (i,n) bfs(i);
For (i,n)
For (j,n)
dp[i][j]=-1;
printf("%.3f",dfs(s,en));
}