bzoj1415: [Noi2005]聪聪和可可

来源:互联网 发布:php转盘抽奖程序 编辑:程序博客网 时间:2024/05/16 11:50

传送门
记忆化搜索。
用f[i][j]表示两个人物在i和j时的期望值。
然后枚举各种情况:
1.重合:答案为0
2.差两步之内:答案为1
3.差2步以上:走两步后的f值+1
取一个平均值就可以了。

#include<cstdlib>  #include<iostream>  #include<cstdio>  #include<cmath>  #include<algorithm>  #include<cstring>using namespace std;const int M=1005;struct edge{int to,next;}e[M*2];int head[M],deg[M],p[M][M],dis[M],q[100005],v[M],from[M];int tot,n,m,pp,qq,x,y;double f[M][M];inline void add(int x,int y){    deg[x]++;    e[++tot].to=y;    e[tot].next=head[x];    head[x]=tot;}inline void bfs(int st){    int h=0,t=1,x;    memset(dis,1,sizeof(dis));    dis[st]=0; q[1]=st;    while (h<t){        x=q[++h];        v[x]=0;        for (int i=head[x];i;i=e[i].next)            if (dis[e[i].to]>dis[x]+1||dis[e[i].to]==dis[x]+1&&from[e[i].to]>x){                dis[e[i].to]=dis[x]+1;                from[e[i].to]=x;                if (!v[e[i].to]){                    v[e[i].to]=1;                    q[++t]=e[i].to;                }            }    }    for (int i=1;i<=n;i++)        if (i!=st) p[i][st]=from[i];}double dfs(int x,int y){    if (x==y) return 0;    if (p[x][y]==y||p[p[x][y]][y]==y) return 1;    if (f[x][y]>-1) return f[x][y];    int tmp=p[p[x][y]][y];    double p=1;    for (int i=head[y];i;i=e[i].next) p+=dfs(tmp,e[i].to)/deg[y];    return f[x][y]=p+dfs(tmp,y)/deg[y];}int main(){      scanf("%d%d%d%d",&n,&m,&pp,&qq);    for (int i=1;i<=n;i++) deg[i]=1;    for (int i=1;i<=m;i++){        scanf("%d%d",&x,&y);        add(x,y);        add(y,x);    }    for (int i=1;i<=n;i++) bfs(i);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++) f[i][j]=-2;    printf("%.3lf",dfs(pp,qq));}
0 0
原创粉丝点击