概率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;
}

 

posted on 2019-06-17 11:07  zsben  阅读(210)  评论(0编辑  收藏  举报

导航