BZOJ1415 聪聪和可可

来源:互联网 发布:异构数据库交互 编辑:程序博客网 时间:2024/05/21 08:36

BZOJ1415 聪聪和可可

期望Dp

题解:

f[i][j]表示聪聪在点i,可可在点j时的期望步数。

  • i==j时,f[i][j]=0
  • i按找要求走一步或两步能走到j时,f[i][j]=1
  • 否则:
    f[i][j]=f[i][j]+1+(f[i][j]+1)du[j]+1

    i’是i按照要求走两步后的点,j’是与j相连的点。

对了多说一句,它满足无后效性,就是两点之间的距离会越来越近。记忆化搜索即可。

Code:

#include <iostream>#include <cstring>#include <cstdio>#include <queue> #define MP make_pairusing namespace std;const int N = 1005;int n,m,du[N],path[N][N]; double f[N][N]; bool vis[N]; int dis[N][N];struct Edge{    int to,next;} e[N*2];int head[N], ec; void add(int a,int b){    ec++; e[ec].to=b; e[ec].next=head[a]; head[a]=ec;}void bfs(int S){    memset(vis,false,sizeof(vis));    queue<int> q; vis[S]=true; dis[S][S]=0; q.push(S);     while(!q.empty()){        int u=q.front(); q.pop();        for(int i=head[u];i;i=e[i].next){            int v=e[i].to;             if(!vis[v]){                 vis[v]=true; dis[S][v]=dis[S][u]+1; q.push(v);             }        }    }}double dp(int i,int j){    double &ans=f[i][j];    if(ans>-0.1) return ans;  //ans>=0    if(i==j) return ans=0;    int ii=path[i][j]; if(ii==j) return ans=1;    ii=path[ii][j]; if(ii==j) return ans=1;    ans=0; ans+=(dp(ii,j)+1)/(du[j]+1);    for(int tp=head[j];tp;tp=e[tp].next){        int jj=e[tp].to;        ans+=(dp(ii,jj)+1)/(du[j]+1);    }    return ans;}int main(){    freopen("a.in","r",stdin);    int cc,kk,a,b;    scanf("%d%d%d%d",&n,&m,&cc,&kk);    for(int i=1;i<=m;i++){        scanf("%d%d",&a,&b);        add(a,b); add(b,a);        du[a]++; du[b]++;    }    for(int i=1;i<=n;i++) bfs(i);    for(int u=1;u<=n;u++){        for(int v=1;v<=n;v++){            path[u][v]=u;            for(int i=head[u];i;i=e[i].next){                int p=e[i].to;                if(dis[p][v]<dis[path[u][v]][v] || (dis[p][v]==dis[path[u][v]][v] && p<path[u][v]))                    path[u][v]=p;            }        }    }     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=-1;    printf("%.3f\n",dp(cc,kk));}

感谢mengcier订正

原创粉丝点击