[数学期望]BZOJ 1415

来源:互联网 发布:oppo应用分身软件 编辑:程序博客网 时间:2024/05/17 02:13

Description
这里写图片描述
题解
既然是平均情况,显然就是求数学期望。我们会发现,每一个时刻猫鼠之间的最短路径一定是减小了,所以不会出现转圈的情况,所以可以用记忆化搜索,用f[x][y]表示猫在节点x,鼠在节点y,猫鼠相遇的期望值。题目中最终要的就是要知道猫的下一步会走到哪里,可以枚举每个点,然后BFS刷最短路,最后枚举一下,O(N2)的复杂度就可以构造出来。所以转移方程:

f[x][y]=1+DP(nxt,son[j])degree[y]+1
其中nxt表示猫下一步走到的节点。显然,如果x=y,f[x][y]=0,如果猫走的时候已经抓到了老鼠,那么f[x][y]=1;
给出代码:

#include<cstdio>#include<cstring>#include<algorithm>#define maxn 1006using namespace std;int n,e,p1,p2,tot,lnk[maxn],son[maxn*2],nxt[maxn*2],ent[maxn],dis[maxn],que[maxn],    p[maxn][maxn];bool vis[maxn];double INF,f[maxn][maxn];int _read(){    char ch=getchar();int sum=0;    while(!(ch>='0'&&ch<='9'))ch=getchar();    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=getchar();    return sum;}void add(int x,int y){    nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot;ent[x]++;}void bfs(int x){    memset(vis,1,sizeof(vis));    int hed=0,tal=1;que[1]=x;vis[x]=0;dis[x]=0;    while(hed!=tal){        for(int j=lnk[que[++hed]];j;j=nxt[j]) if(vis[son[j]]){            que[++tal]=son[j];            vis[son[j]]=0;            dis[son[j]]=dis[que[hed]]+1;        }    }}double DP(int x,int y){    if(x==y){return f[x][y]=0;}    if(f[x][y]!=INF)return f[x][y];    if(p[x][y]==y)return f[x][y]=1;    if(p[p[x][y]][y]==y)return f[x][y]=1;    f[x][y]=1;    f[x][y]+=DP(p[p[x][y]][y],y)/(ent[y]+1);    for(int j=lnk[y];j;j=nxt[j])if(son[j]!=x)     if(p[x][son[j]]!=son[j]) f[x][y]+=DP(p[p[x][y]][y],son[j])/(ent[y]+1);    return f[x][y];}int main(){    freopen("forest.in","r",stdin);    freopen("forest.out","w",stdout);    n=_read();e=_read();p1=_read();p2=_read();    for(int i=1,x,y;i<=e;i++)x=_read(),y=_read(),add(x,y),add(y,x);    memset(p,63,sizeof(p));memset(f,127,sizeof(f));INF=f[0][0];    for(int i=1;i<=n;i++){        bfs(i);        for(int j=1;j<=n;j++)         for(int k=lnk[j];k;k=nxt[k]) if((dis[son[k]]+1==dis[j])&&(son[k]<p[j][i]))p[j][i]=son[k];    }    printf("%.3lf",DP(p1,p2));    return 0;}
0 0
原创粉丝点击