[bzoj1415] 聪聪和可可

[bzoj1415] 聪聪和可可


对于任意一对位置x,y我们可以找到聪聪的行走方案。(这个可以BFS跑)

然后我们用f[x,y]表示聪聪在x,可可在y抓住的期望时间,于是转移方程是:

if(x==y)f[x][y]=0,
if(x走两步能到y)f[x][y]=1,
else 
    f[x][y]=(sigma(f[x_nxtpos][y_nxtpos])+1)/(d[y]+1);

记忆化搜索转移。

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+2,M=2e3+2;
const int INF=0x3f3f3f3f;
int d[N],n,m,C,T;
int hed[N],nxt[M],to[M],cnt;
inline void adde(int u,int v){
    cnt++;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;
}
queue<int>q;
int going[N][N];
bool vis[N];
int dis[N];
inline void bfs(int s){
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    for(int i=1;i<=n;i++)dis[i]=INF;
    vis[s]=true;
    for(int i=hed[s];i;i=nxt[i]){
        int v=to[i];
        going[s][v]=v;vis[v]=true,dis[v]=1;
        q.push(v);
    }
    vis[s]=true;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=hed[u];i;i=nxt[i]){
            int v=to[i];
            if(dis[v]>=dis[u]+1)
                if(!vis[v]){
                    dis[v]=dis[u]+1;
                    going[s][v]=going[s][u];
                    vis[v]=true;
                    q.push(v);
                }
                else going[s][v]=min(going[s][u],going[s][v]);
        }
    }
}

double f[N][N];

double DP(int x,int y){
    int arv=going[going[x][y]][y];
    if(f[x][y]>0)return f[x][y];
    if(x==y)return 0;
    if(going[x][y]==y||arv==y)return f[x][y]=1;
    double sum=DP(arv,y);
    for(int i=hed[y];i;i=nxt[i])sum+=DP(arv,to[i]);
    return f[x][y]=sum/(d[y]+1)+1;
}

int main()
{
    scanf("%d%d",&n,&m);
    scanf("%d%d",&C,&T);
    for(int i=1;i<=m;i++){
        int u,v;scanf("%d%d",&u,&v);
        adde(u,v);adde(v,u);
        d[u]++,d[v]++;
    }
    for(int i=1;i<=n;i++)
        bfs(i);
    double ans=DP(C,T);
    printf("%.3lf\n",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/83117463