NOI 2005 聪聪和可可 [期望DP]

  一个连通的图上有一只猫和老鼠,猫每次能移动一步,会选择到老鼠的最短路去移动,如果有多个选择,移动到标号最小的一个点。如果一步没有抓到老鼠的话,猫可以连续继续移动一步。接着老鼠会随机移动到他附近的一个点或者留在原地,每种移动的概率是1/(该点的度+1)。求猫平均几次可以抓到老鼠。

  p[i][j]表示猫在i老鼠在j猫下一步会选择的点,对每个点bfs一遍可以预处理出来。f[i][j]表示猫在i,老鼠在j猫抓到老鼠的期望,则有

  

  f[i,i]=0,p[i,j]==j或者p[p[i,j],j]==j时f[i][j]=1。

  

 1 #include <string.h>
 2 #include <stdio.h>
 3 #define MAXN 1005
 4 struct edge{
 5     int v,n;
 6 }e[MAXN*2];
 7 int first[MAXN],es;
 8 int n,m,c1,c2,tu,tv;
 9 int p[MAXN][MAXN],deg[MAXN];
10 double d[MAXN][MAXN];
11 void addedge(int u,int v){
12     deg[u]++,e[es].v=v,e[es].n=first[u],first[u]=es++;
13 }
14 int vis[MAXN],q[MAXN],front,rear;
15 void bfs(int s){
16     memset(vis,-1,sizeof vis);vis[s]=0;
17     q[front=rear=0]=s,rear++;
18     while(front<rear){
19         int u=q[front++];
20         for(int i=first[u];i!=-1;i=e[i].n){
21             int v=e[i].v;
22             if(vis[v]==-1)vis[v]=vis[u]+1,q[rear++]=v,p[v][s]=u;
23             else if(vis[v]==vis[u]+1&&p[v][s]>u)p[v][s]=u;
24         }
25     }
26 }
27 double dp(int c1,int c2){
28     if(d[c1][c2])return d[c1][c2];
29     if(c1==c2)return 0.0;
30     if(p[p[c1][c2]][c2]==c2||p[c1][c2]==c2)return 1.0;
31     double tmp=dp(p[p[c1][c2]][c2],c2);
32     for(int i=first[c2];i!=-1;i=e[i].n)
33         tmp+=dp(p[p[c1][c2]][c2],e[i].v);
34     return d[c1][c2]=tmp/(deg[c2]+1)+1;
35 }
36 int main(){
37     while(scanf("%d%d",&n,&m)!=EOF){
38         scanf("%d%d",&c1,&c2);
39         memset(deg,0,sizeof deg);
40         memset(first,-1,sizeof first);es=0;
41         for(int i=0;i<m;i++){
42             scanf("%d%d",&tu,&tv);
43             addedge(tu,tv);
44             addedge(tv,tu);
45         }
46         for(int i=1;i<=n;i++)
47             for(int j=1;j<=n;j++)p[i][j]=d[i][j]=0;
48         for(int i=1;i<=n;i++)bfs(i);
49         printf("%.3f\n",dp(c1,c2));
50     }
51     return 0;
52 }

 

  

posted @ 2012-08-31 14:35  Burn_E  阅读(357)  评论(3)    收藏  举报