zoukankan      html  css  js  c++  java
  • BZOJ1415 聪聪与可可

    传送门

    题目大意:

    一张无向图上有一只猫和一只老鼠,猫先走,鼠后走。猫每次会向与其相邻的并且距离老鼠最近的点移动(若距离相等去编号较小的),如果移动一步后还没吃到老鼠,还可以再移动一步(算在一个时间内的)。老鼠每次会向相邻的点移动或者不移动,所有选择的概率相同。问猫期望多少时间能够吃到老鼠。

    题目分析:

    期望dp:设(f[i][j])表示猫在i点,鼠在j点,猫吃到鼠的期望步数。(P[i][j])表示与i相邻的点中距离j最近且编号最小的点(bfs预处理)。(deg[i])表示i的度数。
    那么:$$f[i][j] = f[P[P[i][j]][j] / (deg[v] + 1) + sum{f[P[P[i][j]][v_j] / (deg[v] + 1)} + 1$$
    方程上面两式分别对应:

    1. 猫移动,鼠不移动。
    2. 猫移动,鼠移动。
      初始化:$$f[i][i] = 0$$

    [f[i][j] = 1(dis[i][j] le 2) ]

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1050, M = 1050,OO = 0x3f3f3f3f;
    #define eps 1e-8
    int n, m, p, q, vt;
    int ecnt, adj[N], nxt[M << 1], go[M << 1], P[N][N], dist[N][N], deg[N];
    double f[N][N];
    int vst[N];
    struct node{
        int now, dis;
        node(){}
        node(int _now, int _dis):now(_now), dis(_dis){}
    };
    
    inline void addEdge(int u, int v){
        nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v;
        deg[u]++;
    }
    
    inline void Bfs(int i){
        static queue<node> que;
        while(!que.empty()) que.pop();
        vt++;
        que.push(node(i, 0));
        vst[i] = vt;
        while(!que.empty()){
            node u = que.front(); que.pop();
            for(int e = adj[u.now]; e; e = nxt[e]){
                int v = go[e];
                if(vst[v] == vt) continue;
                dist[i][v] = u.dis + 1;
                vst[v] = vt;
                node ret = node(v, u.dis + 1);
                que.push(ret);
            }
        }
    }
    
    inline void init(){
        memset(dist, OO, sizeof dist);
        for(int i = 1; i <= n; i++) dist[i][i] = 0, Bfs(i);
        for(int i = 1; i <= n; i++){
            P[i][i] = i;
            for(int j = i + 1; j <= n; j++){
                /*与i相邻的与j最近的点*/
                int mndis = OO, point = 0;
                for(int e = adj[i]; e; e = nxt[e]){
                    int v = go[e];
                    if(dist[v][j] < mndis){
                        mndis = dist[v][j];
                        point = v;
                    }
                    else if(dist[v][j] == mndis && v < point) point = v;
                }
                P[i][j] = point;
                /*与j相邻的与i最近的点*/
                mndis = OO, point = 0;
                for(int e = adj[j]; e; e = nxt[e]){
                    int v = go[e];
                    if(dist[v][i] < mndis){
                        mndis = dist[v][i];
                        point = v;
                    }
                    else if(dist[v][i] == mndis && v < point) point = v;
                }
                P[j][i] = point;
            }
        }
    }
    
    inline double F(int u, int v){
        if(f[u][v] >= 0) return f[u][v];
        f[u][v] = 1.0;
        int to = P[P[u][v]][v];
        double p = 1.0 / (1.0*deg[v] + 1.0);
        f[u][v] += F(to, v) * p;
        for(int e = adj[v]; e; e = nxt[e]){
            int vj = go[e];
            f[u][v] += F(to, vj) * p;
        }
        return f[u][v];
    }
    
    int main(){
        freopen("h.in", "r", stdin);
        scanf("%d%d%d%d", &n, &m, &p, &q);
        for(int i = 1; i <= m; i++){
            int x, y;
            scanf("%d%d", &x, &y);
            addEdge(x, y), addEdge(y, x);
        }
        init();
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                f[i][j] = -5555;
        for(int i = 1; i <= n; i++){
            f[i][i] = 0;
            for(int j = i + 1; j <= n; j++){
                if(dist[i][j] <= 2) f[i][j] = f[j][i] = 1.0;
            }
        }
        printf("%.3lf
    ", F(p, q));
    }
    
    
  • 相关阅读:
    【书上讲解】平面上最近点对问题
    【书上讲解】快速排序
    【书上讲解】归并排序的非递归写法
    【例题 2-6】汉诺塔问题
    汉诺塔问题详解
    【例题2-5】整数的划分
    【例题2-4】排列问题
    【1-5】最大间隙问题
    【1-4】金币阵列问题
    【1-2】字典序问题
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7751196.html
Copyright © 2011-2022 走看看