算是正式开始接触期望DP了吧,以前在NOIP之前TY比赛里做过一些,基本上都是根据初中的概率知识乱搞的,但事实上这种期望概率动规题还是可以很难的。
这个题是看论文上的题解,算是比较基础的期望dp了吧。首先需要预处理一些东西:way[i][j]表示聪聪在i可可在j点时聪聪会走到哪个点,t[i]表示i点的度,next[i][j]表示和i点相连的第j个点是谁(就是可可在i点时可以走到的点的集合,这个集合的大小是t[i])。其中way[i][j]我是枚举顶点dfs的。
然后就是一个方程了:f[i][j]=f[way[way[i][j]][j],j](可可不动)+Σf[way[way[i][j]][j],next[j][k]](可可走向next[j][k]),f[i][j]=f[i][j]/(t[j]+1)+1(注意这里的+1,就是说聪聪一次可以走两步但是算在一个时间里,所以要给步数加1)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 1200 7 #define maxm 1200000 8 #define inf 1000000000 9 using namespace std; 10 double f[maxn][maxn]; 11 int way[maxn][maxn],next[maxn][maxn],t[maxn],dis[maxn], v[maxn]; 12 int n,m,tot,st,ed; 13 14 void search(int rot,int son,int now) 15 { 16 for (int j=1;j<=t[now];j++) 17 { 18 int k=next[now][j]; 19 if (dis[k]==-1||dis[now]+1<dis[k]) 20 { 21 dis[k]=dis[now]+1; 22 way[rot][k]=son; 23 search(rot,son,k); 24 } 25 } 26 } 27 28 double find(int i,int j) 29 { 30 if (f[i][j]!=-1) return f[i][j]; 31 if (i==j) return f[i][j]=0; 32 if (way[i][j]==j||way[way[i][j]][j]==j) return f[i][j]=1; 33 f[i][j]=0; 34 for (int k=1;k<=t[j];k++) 35 f[i][j]+=find(way[way[i][j]][j],next[j][k]); 36 f[i][j]+=find(way[way[i][j]][j],j); 37 f[i][j]=f[i][j]/(t[j]+1)+1; 38 return f[i][j]; 39 } 40 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 scanf("%d%d",&st,&ed); 45 int x,y; 46 for (int i=1;i<=m;i++) 47 { 48 scanf("%d%d",&x,&y); 49 next[x][++t[x]]=y; 50 next[y][++t[y]]=x; 51 } 52 for (int i=1;i<=n;i++) 53 { 54 memset(dis,-1,sizeof(dis)); 55 dis[i]=0; 56 sort(next[i]+1,next[i]+t[i]+1); 57 for (int j=1;j<=t[i];j++) 58 { 59 dis[next[i][j]]=0; 60 way[i][next[i][j]]=next[i][j]; 61 search(i,next[i][j],next[i][j]); 62 } 63 } 64 for (int i=1;i<=n;i++) 65 for (int j=1;j<=n;j++) 66 f[i][j]=-1; 67 double ans=find(st,ed); 68 printf("%.3lf\n",ans); 69 return 0; 70 }