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));
    }
    
    
  • 相关阅读:
    CF1454F Array Partition
    leetcode1883 准时抵达会议现场的最小跳过休息次数
    leetcode1871 跳跃游戏 VII
    leetcode1872 石子游戏VIII
    CF1355C Count Triangles
    CF1245D Shichikuji and Power Grid
    CF1368C Even Picture
    CF1368D AND, OR and square sum
    CF1395C Boboniu and Bit Operations
    SpringBoot和开发热部署
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7751196.html
Copyright © 2011-2022 走看看