hdu 4035 概率,求期望dp

来源:互联网 发布:精易编程助手 哪里下载 编辑:程序博客网 时间:2024/06/05 13:17

列方程,系数替换化简,递推求解

参考:http://www.cnblogs.com/kuangbin/archive/2012/10/03/2711108.html

/*HDU 4035    dp求期望的题。    题意:    有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,    从结点1出发,开始走,在每个结点i都有3种可能:        1.被杀死,回到结点1处(概率为ki)        2.找到出口,走出迷宫 (概率为ei)        3.和该点相连有m条边,随机走一条    求:走出迷宫所要走的边数的期望值。    设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望。E[1]即为所求。    叶子结点:    E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);         = ki*E[1] + (1-ki-ei)*E[father[i]] + (1-ki-ei);    非叶子结点:(m为与结点相连的边数)    E[i] = ki*E[1] + ei*0 + (1-ki-ei)/m*( E[father[i]]+1 + ∑( E[child[i]]+1 ) );         = ki*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei)/m*∑(E[child[i]]) + (1-ki-ei);    设对每个结点:E[i] = Ai*E[1] + Bi*E[father[i]] + Ci;    对于非叶子结点i,设j为i的孩子结点,则    ∑(E[child[i]]) = ∑E[j]                   = ∑(Aj*E[1] + Bj*E[father[j]] + Cj)                   = ∑(Aj*E[1] + Bj*E[i] + Cj)    带入上面的式子得    (1 - (1-ki-ei)/m*∑Bj)*E[i] = (ki+(1-ki-ei)/m*∑Aj)*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei) + (1-ki-ei)/m*∑Cj;    由此可得    Ai =        (ki+(1-ki-ei)/m*∑Aj)   / (1 - (1-ki-ei)/m*∑Bj);    Bi =        (1-ki-ei)/m            / (1 - (1-ki-ei)/m*∑Bj);    Ci = ( (1-ki-ei)+(1-ki-ei)/m*∑Cj ) / (1 - (1-ki-ei)/m*∑Bj);    对于叶子结点    Ai = ki;    Bi = 1 - ki - ei;    Ci = 1 - ki - ei;    从叶子结点开始,直到算出 A1,B1,C1;    E[1] = A1*E[1] + B1*0 + C1;    所以    E[1] = C1 / (1 - A1);    若 A1趋近于1则无解...*/

#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>#include <bitset>using namespace std;//LOOP#define FE(i, a, b) for(int i = (a); i <= (b); ++i)#define FED(i, b, a) for(int i = (b); i>= (a); --i)#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(A,value) memset(A,value,sizeof(A))//INPUT#define RI(n) scanf("%d", &n)#define RII(n, m) scanf("%d%d", &n, &m)#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)#define RS(s) scanf("%s", s)typedef long long LL;const int INF = 1000000000;const int MOD = 1000000007;const int MAXN = 11000;const double eps = 1e-10;double A[MAXN], B[MAXN], C[MAXN];double k[MAXN], e[MAXN];vector<int>adj[MAXN];int n, m;bool dfs(int u, int fa){    int m = adj[u].size();    double pp = 1 - k[u] - e[u];///中间变量可能损失精度    A[u] = k[u];    B[u] = pp / m;    C[u] = pp;    double tmp = 0;    REP(i, m)    {        int v = adj[u][i];        if (v == fa) continue;        if (!dfs(v, u)) return false;        A[u] += pp / m * A[v];        C[u] += pp / m * C[v];        tmp += pp / m * B[v];    }    if (fabs(1 - tmp) < eps)///判断    return false;    A[u] /= (1 - tmp);    B[u] /= (1 - tmp);    C[u] /= (1 - tmp);    return true;}int main(){    int T;    int ncase = 1;    RI(T);    while (T--)    {        RI(n);        REP(i, n + 1) adj[i].clear();        REP(i, n - 1)        {            int u, v;            RII(u, v);            adj[u].push_back(v);            adj[v].push_back(u);        }        FE(i, 1, n)        {            scanf("%lf%lf", &k[i], &e[i]);            k[i] /= 100;            e[i] /= 100;        }        printf("Case %d: ", ncase++);        if (dfs(1, -1) && fabs(1 - A[1]) > eps)///判断        {            printf("%.6lf\n", C[1] / (1 - A[1]));        }        else printf("impossible\n");    }    return 0;}


原创粉丝点击