• 概率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;
    }
  • 相关阅读:
    基本MVVM 和 ICommand用法举例(转)
    WPF C# 命令的运行机制
    628. Maximum Product of Three Numbers
    605. Can Place Flowers
    581. Shortest Unsorted Continuous Subarray
    152. Maximum Product Subarray
    216. Combination Sum III
    448. Find All Numbers Disappeared in an Array
    268. Missing Number
    414. Third Maximum Number
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11038651.html
Copyright © 2020-2023  润新知