zoukankan      html  css  js  c++  java
  • 概率dp的迭代方式小结——zoj3329,hdu4089,hdu4035

    在推导期望方程时我们常常会遇到dp[i]和其他项有关联,那么这时候我们就难以按某个顺序进行递推

    即难以通过已经确定的项来求出新的项

    即未知数的相互关系是循环的

    但是我们又可以确定和dp[i]相关联的项是有规律的,即存在一个可以递推dp[i]的通项公式,那么不妨设置未知数,通过原方程的迭代来打破这种循环

    为了完成递推,我们需要通过递推和dp[i]有关的参数来间接求出dp[i]

    比如递推方程dp[i]总是和dp[1]有关,那么我们可以肯定dp[i]=ai*dp[1]+b[i]

    那么用这个方程进行迭代,最后可以发现ai是能够逆着递推的

    zoj3329:dp[i]=a[i]dp[0]+b[i]

    这题dp[i]总是和dp[0]有关,假设dp[i+k]的值都知道了(等价于常数b[i]),那么a[i]就是个可以递推的项

    hdu:dp[i][j]=a[j]*dp[i][i]+c[j]

    hdu4035:树上迭代,因为正常的顺序是从叶子推导到根,但是每个结点会受到dp[rt]和dp[fa]的影响, 所以这两项要用两个参数来迭代

      dp[u]=a[u]*dp[rt]+b[u]*dp[fa]+c[u]

    #include <cstdio>
    #include <iostream>
    #include <vector>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 10000 + 5;
    
    double e[MAXN], k[MAXN];
    double A[MAXN], B[MAXN], C[MAXN];
    
    vector<int> v[MAXN];
    
    bool search(int i, int fa)
    {
        if ( v[i].size() == 1 && fa != -1 )
        {
            A[i] = k[i];
            B[i] = 1 - k[i] - e[i];
            C[i] = 1 - k[i] - e[i];
            return true;
        }
    
        A[i] = k[i];
        B[i] = (1 - k[i] - e[i]) / v[i].size();
        C[i] = 1 - k[i] - e[i];
        double tmp = 0;
        
        for (int j = 0; j < (int)v[i].size(); j++)
        {
            if ( v[i][j] == fa ) continue;
            if ( !search(v[i][j], i) ) return false;
            A[i] += A[v[i][j]] * B[i];
            C[i] += C[v[i][j]] * B[i];
            tmp  += B[v[i][j]] * B[i];
        }
        if ( fabs(tmp - 1) < 1e-10 ) return false;
        A[i] /= 1 - tmp;
        B[i] /= 1 - tmp;
        C[i] /= 1 - tmp;
        return true;
    }
    
    int main()
    {
        int nc, n, s, t;
    
        cin >> nc;
        for (int ca = 1; ca <= nc; ca++)
        {
            scanf("%d",&n);
            for (int i = 1; i <= n; i++)
                v[i].clear();
    
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d",&s,&t);
                v[s].push_back(t);
                v[t].push_back(s);
            }
            for (int i = 1; i <= n; i++)
            {
                scanf("%lf%lf",&k[i],&e[i]);
                k[i] /= 100.0;
                e[i] /= 100.0;
            }
            
            cout << "Case " << ca << ": ";
            if ( search(1, -1) && fabs(1 - A[1]) > 1e-10 )
                cout << C[1]/(1 - A[1]) << endl;
            else
                cout << "impossible" << endl;
        }
        return 0;
    }
    #include <cstdio>
    #include <iostream>
    #include <vector>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 10000 + 5;
    
    double e[MAXN], k[MAXN];
    double A[MAXN], B[MAXN], C[MAXN];
    
    vector<int> v[MAXN];
    
    bool search(int i, int fa)
    {
        if ( v[i].size() == 1 && fa != -1 )
        {
            A[i] = k[i];
            B[i] = 1 - k[i] - e[i];
            C[i] = 1 - k[i] - e[i];
            return true;
        }
    
        A[i] = k[i];
        B[i] = (1 - k[i] - e[i]) / v[i].size();
        C[i] = 1 - k[i] - e[i];
        double tmp = 0;
        
        for (int j = 0; j < (int)v[i].size(); j++)
        {
            if ( v[i][j] == fa ) continue;
            if ( !search(v[i][j], i) ) return false;
            A[i] += A[v[i][j]] * B[i];
            C[i] += C[v[i][j]] * B[i];
            tmp  += B[v[i][j]] * B[i];
        }
        if ( fabs(tmp - 1) < 1e-10 ) return false;
        A[i] /= 1 - tmp;
        B[i] /= 1 - tmp;
        C[i] /= 1 - tmp;
        return true;
    }
    
    int main()
    {
        int nc, n, s, t;
    
        cin >> nc;
        for (int ca = 1; ca <= nc; ca++)
        {
            scanf("%d",&n);
            for (int i = 1; i <= n; i++)
                v[i].clear();
    
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d",&s,&t);
                v[s].push_back(t);
                v[t].push_back(s);
            }
            for (int i = 1; i <= n; i++)
            {
                scanf("%lf%lf",&k[i],&e[i]);
                k[i] /= 100.0;
                e[i] /= 100.0;
            }
            
            cout << "Case " << ca << ": ";
            if ( search(1, -1) && fabs(1 - A[1]) > 1e-10 )
                cout << C[1]/(1 - A[1]) << endl;
            else
                cout << "impossible" << endl;
        }
        return 0;
    }
    #include <cstdio>
    #include <iostream>
    #include <vector>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 10000 + 5;
    
    double e[MAXN], k[MAXN];
    double A[MAXN], B[MAXN], C[MAXN];
    
    vector<int> v[MAXN];
    
    bool search(int i, int fa)
    {
        if ( v[i].size() == 1 && fa != -1 )
        {
            A[i] = k[i];
            B[i] = 1 - k[i] - e[i];
            C[i] = 1 - k[i] - e[i];
            return true;
        }
    
        A[i] = k[i];
        B[i] = (1 - k[i] - e[i]) / v[i].size();
        C[i] = 1 - k[i] - e[i];
        double tmp = 0;
        
        for (int j = 0; j < (int)v[i].size(); j++)
        {
            if ( v[i][j] == fa ) continue;
            if ( !search(v[i][j], i) ) return false;
            A[i] += A[v[i][j]] * B[i];
            C[i] += C[v[i][j]] * B[i];
            tmp  += B[v[i][j]] * B[i];
        }
        if ( fabs(tmp - 1) < 1e-10 ) return false;
        A[i] /= 1 - tmp;
        B[i] /= 1 - tmp;
        C[i] /= 1 - tmp;
        return true;
    }
    
    int main()
    {
        int nc, n, s, t;
    
        cin >> nc;
        for (int ca = 1; ca <= nc; ca++)
        {
            scanf("%d",&n);
            for (int i = 1; i <= n; i++)
                v[i].clear();
    
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d",&s,&t);
                v[s].push_back(t);
                v[t].push_back(s);
            }
            for (int i = 1; i <= n; i++)
            {
                scanf("%lf%lf",&k[i],&e[i]);
                k[i] /= 100.0;
                e[i] /= 100.0;
            }
            
            cout << "Case " << ca << ": ";
            if ( search(1, -1) && fabs(1 - A[1]) > 1e-10 )
                cout << C[1]/(1 - A[1]) << endl;
            else
                cout << "impossible" << endl;
        }
        return 0;
    }
    #include <cstdio>
    #include <iostream>
    #include <vector>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 10000 + 5;
    
    double e[MAXN], k[MAXN];
    double A[MAXN], B[MAXN], C[MAXN];
    
    vector<int> v[MAXN];
    
    bool search(int i, int fa)
    {
        if ( v[i].size() == 1 && fa != -1 )
        {
            A[i] = k[i];
            B[i] = 1 - k[i] - e[i];
            C[i] = 1 - k[i] - e[i];
            return true;
        }
    
        A[i] = k[i];
        B[i] = (1 - k[i] - e[i]) / v[i].size();
        C[i] = 1 - k[i] - e[i];
        double tmp = 0;
        
        for (int j = 0; j < (int)v[i].size(); j++)
        {
            if ( v[i][j] == fa ) continue;
            if ( !search(v[i][j], i) ) return false;
            A[i] += A[v[i][j]] * B[i];
            C[i] += C[v[i][j]] * B[i];
            tmp  += B[v[i][j]] * B[i];
        }
        if ( fabs(tmp - 1) < 1e-10 ) return false;
        A[i] /= 1 - tmp;
        B[i] /= 1 - tmp;
        C[i] /= 1 - tmp;
        return true;
    }
    
    int main()
    {
        int nc, n, s, t;
    
        cin >> nc;
        for (int ca = 1; ca <= nc; ca++)
        {
            scanf("%d",&n);
            for (int i = 1; i <= n; i++)
                v[i].clear();
    
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d",&s,&t);
                v[s].push_back(t);
                v[t].push_back(s);
            }
            for (int i = 1; i <= n; i++)
            {
                scanf("%lf%lf",&k[i],&e[i]);
                k[i] /= 100.0;
                e[i] /= 100.0;
            }
            
            cout << "Case " << ca << ": ";
            if ( search(1, -1) && fabs(1 - A[1]) > 1e-10 )
                cout << C[1]/(1 - A[1]) << endl;
            else
                cout << "impossible" << endl;
        }
        return 0;
    }
    #include <cstdio>
    #include <iostream>
    #include <vector>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 10000 + 5;
    
    double e[MAXN], k[MAXN];
    double A[MAXN], B[MAXN], C[MAXN];
    
    vector<int> v[MAXN];
    
    bool search(int i, int fa)
    {
        if ( v[i].size() == 1 && fa != -1 )
        {
            A[i] = k[i];
            B[i] = 1 - k[i] - e[i];
            C[i] = 1 - k[i] - e[i];
            return true;
        }
    
        A[i] = k[i];
        B[i] = (1 - k[i] - e[i]) / v[i].size();
        C[i] = 1 - k[i] - e[i];
        double tmp = 0;
        
        for (int j = 0; j < (int)v[i].size(); j++)
        {
            if ( v[i][j] == fa ) continue;
            if ( !search(v[i][j], i) ) return false;
            A[i] += A[v[i][j]] * B[i];
            C[i] += C[v[i][j]] * B[i];
            tmp  += B[v[i][j]] * B[i];
        }
        if ( fabs(tmp - 1) < 1e-10 ) return false;
        A[i] /= 1 - tmp;
        B[i] /= 1 - tmp;
        C[i] /= 1 - tmp;
        return true;
    }
    
    int main()
    {
        int nc, n, s, t;
    
        cin >> nc;
        for (int ca = 1; ca <= nc; ca++)
        {
            scanf("%d",&n);
            for (int i = 1; i <= n; i++)
                v[i].clear();
    
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d",&s,&t);
                v[s].push_back(t);
                v[t].push_back(s);
            }
            for (int i = 1; i <= n; i++)
            {
                scanf("%lf%lf",&k[i],&e[i]);
                k[i] /= 100.0;
                e[i] /= 100.0;
            }
            
            cout << "Case " << ca << ": ";
            if ( search(1, -1) && fabs(1 - A[1]) > 1e-10 )
                cout << C[1]/(1 - A[1]) << endl;
            else
                cout << "impossible" << endl;
        }
        return 0;
    }
  • 相关阅读:
    创建对象的七种方式
    设计模式之工厂模式
    设计模式之单例模式
    排序算法之插入排序
    排序算法之选择排序
    类及对象初体验
    排序算法之冒泡排序
    迭代器和生成器
    装饰器
    函数进阶
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11038651.html
Copyright © 2011-2022 走看看