【样例说明1】
开始时,聪聪和可可分别在景点1和景点4。
第一个时刻,聪聪先走,她向更靠近可可(景点4)的景点走动,走到景点2,然后走到景点3;假定忽略走路所花时间。
可可后走,有两种可能:
第一种是走到景点3,这样聪聪和可可到达同一个景点,可可被吃掉,步数为1,概率为 。
第二种是停在景点4,不被吃掉。概率为 。
到第二个时刻,聪聪向更靠近可可(景点4)的景点走动,只需要走一步即和可可在同一景点。因此这种情况下聪聪会在两步吃掉可可。
所以平均的步数是1* +2* =1.5步。
对于所有的数据,1≤N,E≤1000。
对于50%的数据,1≤N≤50。
#include<stdio.h> #include<string.h> #include<iostream> #include<queue> using namespace std; const int maxn=1010; struct node//边结构 { int v; int cost; node *next; } edge[maxn<<1],*head[maxn]; int ptr,pos[maxn][maxn],vis[maxn],dist[maxn]; int n,e,sx,ex; double dp[maxn][maxn]; queue<int> q; void adde(int u,int v) { edge[ptr].v=v; edge[ptr].next=head[u]; edge[ptr].cost=1; head[u]=&edge[ptr++]; } void spfa(int s)//算最短路并得到pos[i][j] { int u,v; node *p; while(!q.empty()) q.pop(); memset(vis,0,sizeof vis); memset(dist,0x3f,sizeof dist); dist[s]=0; for(p=head[s];p!=NULL;p=p->next)//先预处理起点周围的点 { v=p->v; pos[s][v]=v; q.push(v); dist[v]=1; vis[v]=1; } while(!q.empty()) { u=q.front(); vis[u]=0; q.pop(); for(p=head[u];p!=NULL;p=p->next) { v=p->v; if(dist[u]+p->cost<dist[v]) { dist[v]=dist[u]+p->cost; pos[s][v]=pos[s][u];//更新最优决策点 if(!vis[v]) { q.push(v); vis[v]=1; } } else if(dist[u]+p->cost==dist[v]&&pos[s][u]<pos[s][v]) { pos[s][v]=pos[s][u]; if(!vis[v]) { q.push(v); vis[v]=1; } } } } } void dfs(int u,int v)//计算聪聪在u可可在v。聪聪吃到可可的步数的期望。记忆化搜索 { if(dp[u][v]>=0) return ; int np,cnt=0; double sum=0; node *p; np=pos[pos[u][v]][v]; if(np==v) { dp[u][v]=1; return; } for(p=head[v];p!=NULL;p=p->next) { dfs(np,p->v); sum+=dp[np][p->v]; cnt++;//统计边数 } dfs(np,v); sum+=dp[np][v];//加上可可不动的期望 dp[u][v]=sum/(cnt+1)+1;//走了一步了所以加1 } int main() { int i,j,a,b; while(~scanf("%d%d",&n,&e)) { scanf("%d%d",&sx,&ex); ptr=0; memset(head,0,sizeof head); for(i=1;i<=n;i++) for(j=1;j<=n;j++) dp[i][j]=-1; for(i=0;i<e;i++) { scanf("%d%d",&a,&b); adde(a,b); adde(b,a); } for(i=1;i<=n;i++) { dp[i][i]=0;//相遇直接吃掉步数为0 pos[i][i]=i; spfa(i); } dfs(sx,ex); printf("%.3lf\n",dp[sx][ex]); } return 0; }