Luogu 4206 [NOI2005]聪聪与可可

BZOJ 1415

简单期望 + 记忆化搜索。

发现聪聪每一步走向的地方是在可可的所在位置确定时是确定的,设$nxt_{x, y}$表示聪聪在$x$,可可在$y$时聪聪下一步会走到哪里,我们先预处理出这个$nxt$。

为了预处理$nxt$,我们还需要先预处理一个$d_{x, y}$表示$x$到$y$的最短距离,因为所有边的边权相同,所以我们第一次广搜到一个点的时候就是到这个点的最短路。

假如$d_{x, z} == d_{y, z} + 1$,$dis(x, y) == 1$,那么$z$就是$x$到$y$最短路上的一个点,用它更新$nxt_{x, y}$即可。

 

我们设$f_{x, y}$ 表示聪聪在$x$,可可在$y$时抓到可可的期望步数,显然有:

  $f_{x, y} == 0$  $(x == y)$

  $f_{x, y} == 1$  $(nxt_{x, y} == y)$  或者 $(nxt_{nxt_{x, y}, y} == y)$

而根据期望的性质,可可的随机行走可以表示成这个公式:

  $f_{x, y} = \frac{\sum _{z} f_{nxt_{nxt_{x, y}, y}, z}}{deg_y + 1} + 1$  $z == y$或者$z$可由$y$一步走到。 

记忆化搜索实现。

时间复杂度$O(n^2)$。

Code:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef double db;

const int N = 1005;
const int inf = 0x3f3f3f3f;

int n, m, st, ed, d[N][N];
int tot = 0, head[N], deg[N], nxt[N][N];
db f[N][N];

struct Edge {
    int to, nxt;
} e[N << 1];

inline void add(int from, int to) {
    e[++tot].to = to;
    e[tot].nxt = head[from];
    head[from] = tot;
}

inline void read(int &X) {
    X = 0; char ch = 0; int op = 1;
    for(; ch > '9'|| ch < '0'; ch = getchar())
        if(ch == '-') op = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

inline void chkMin(int &x, int y) {
    if(y < x) x = y;
} 

queue <int> Q;
inline void bfs(int fir, int *dis) {
    Q.push(fir);
    for(int i = 1; i <= n; i++) dis[i] = inf;
    dis[fir] = 0;
    
    for(; !Q.empty(); ) {
        int x = Q.front(); Q.pop();
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(dis[y] == inf) {
                dis[y] = dis[x] + 1;
                Q.push(y);
            }
        }
    } 
}

db dfs(int x, int y) {
    if(f[x][y] != -1.0) return f[x][y];
    if(x == y) return f[x][y] = 0.0;
    if(nxt[x][y] == y) return f[x][y] = 1.0;
    if(nxt[nxt[x][y]][y] == y) return f[x][y] = 1.0;
    
    db res = 0;
    for(int i = head[y]; i; i = e[i].nxt) {
        int to = e[i].to;
        res += dfs(nxt[nxt[x][y]][y], to);
    }
    res += dfs(nxt[nxt[x][y]][y], y);
    
    return f[x][y]= res / (deg[y] + 1) + 1;
}

int main() {
    read(n), read(m), read(st), read(ed);
    for(int x, y, i = 1; i <= m; i++) {
        read(x), read(y);
        add(x, y), add(y, x);
        deg[x]++, deg[y]++; 
    }
    
    for(int i = 1; i <= n; i++) bfs(i, d[i]);
    
/*    for(int i = 1; i <= n; i++, printf("\n"))
        for(int j = 1; j <= n; j++)
            printf("%d ", d[i][j]);    */
    
    memset(nxt, 0x3f, sizeof(nxt));
    for(int x = 1; x <= n; x++) {
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            for(int k = 1; k <= n; k++)
                if(d[x][k] == d[y][k] + 1)
                    chkMin(nxt[x][k], y);
        }
    }
    
/*    for(int i = 1; i <= n; i++, printf("\n"))
        for(int j = 1; j <= n; j++)
            printf("%d ", nxt[i][j]);    */
    
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            f[i][j] = -1.0;
    
    dfs(st, ed);
    
    printf("%.3f\n", f[st][ed]);
    return 0;
}
View Code

 

  

 

posted @ 2018-10-03 18:32  CzxingcHen  阅读(152)  评论(0编辑  收藏  举报