zoukankan      html  css  js  c++  java
  • luoguP4206 [NOI2005]聪聪与可可 期望概率DP

    首先,分析一下这个猫和鼠

    猫每局都可以追老鼠一步或者两步,但是除了最后的一步,肯定走两步快些....

    既然猫走的步数总是比老鼠多,那么它们的距离在逐渐缩小(如果这题只能走一步反而不能做了...)

    猫不知道老鼠下一步走哪里,猫走的时候依据的是老鼠当前的位置

    明显,猫走的位置没有什么规律可言(即使有规律还是会预处理啊.....)

    我们可以在$O(n^2 + nm)$的复杂度内预处理出$s(i, j)$表示猫在$i$,老鼠在$j$时,猫下一步的位置...

    直接设$f(i, j)$表示猫在$i$,老鼠在$j$时猫吃到老鼠的期望步数

    那么有$f(i, i) = 0$

    并且$f(i, s(i, j)) = 1,f(i, s(s(i, j), j)) = 1 (i eq j)$

    其余情况下$f(i, j) = sumlimits_{v = j | e(j, v)} frac{f(s(s(i, j), j), v) + 1}{du[j] + 1}$

    由于猫鼠距离减小,因此转移具有拓扑序

    可以根据猫鼠距离排序转移,也可以直接$dfs$

    由于$dfs$好写,因此这里选择$dfs$

    复杂度$O(n^2 + nm)$

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    #define de double
    #define sid 1005
    #define eid 5005
    #define ri register int
    
    int n, m, s, t, cnp;
    int cap[eid], nxt[eid], node[eid], q[eid];
    int du[sid], dis[sid][sid], nx[sid][sid];
    de f[sid][sid];
    
    void adeg(int u, int v) {
        du[u] ++;
        nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
    }
    
    #define cur node[i]
    void Pre() {
        for(ri u = 1; u <= n; u ++) {
            int fr = 1, to = 0;
            q[++ to] = u; dis[u][u] = 0;
            while(fr <= to) {
                int o = q[fr ++];
                for(ri i = cap[o]; i; i = nxt[i])
                if(dis[u][cur] == 1e5)
                dis[u][cur] = dis[u][o] + 1, q[++ to] = cur;
            }
        }
        for(ri u = 1; u <= n; u ++)
        for(ri v = 1; v <= n; v ++) {
            int w = 1e5;
            for(ri i = cap[u]; i; i = nxt[i])
            if(dis[cur][v] < w || (dis[cur][v] == w && nx[u][v] > cur))
            nx[u][v] = cur, w = dis[cur][v];
        }
    }
    
    de dfs(int a, int b) {
        if(f[a][b] != -1) return f[a][b];
        if(a == b) return f[a][b] = 0;
        int to = nx[a][b], toto = nx[to][b];
        if(to == b || toto == b) return f[a][b] = 1;
        f[a][b] = 0;
        for(int i = cap[b]; i; i = nxt[i])
        f[a][b] += (dfs(toto, cur) + 1) / (de)(du[b] + 1);
        f[a][b] += (dfs(toto, b) + 1) / (de)(du[b] + 1);
        return f[a][b];
    }
    
    int main() {
        n = read(); m = read();
        s = read(); t = read();
        for(ri i = 1; i <= m; i ++) {
            int u = read(), v = read();
            adeg(u, v); adeg(v, u);
        }
    
        for(ri i = 1; i <= n; i ++)
        for(ri j = 1; j <= n; j ++)
        dis[i][j] = 1e5, f[i][j] = -1;
    
        Pre();
        printf("%.3lf
    ", dfs(s, t));
        return 0;
    }
  • 相关阅读:
    jq serialize 系列化 乱码 解决办法
    如何使用 TP中的公共函数 (定义在common/common.php中的函数)
    Sublime Text 使用技巧
    动态创建菜单
    jq中写PHP
    redis 管道
    微信强大的demo
    【Hibernate异常处理-1】java.lang.NoSuchMethodError: javax.persistence.JoinColumn.foreignKey()Ljavax/persistence/ForeignKey;
    【Hibernate学习笔记-5.2】使用@Temporal修饰日期类型的属性
    【Hibernate学习笔记-5.1】使用@Transient修饰不想持久保存的属性
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9513915.html
Copyright © 2011-2022 走看看