zoukankan      html  css  js  c++  java
  • HDU 4035Maze(概率DP)

    HDU 4035   Maze

    体会到了状态转移,化简方程的重要性

    题解转自http://blog.csdn.net/morgan_xww/article/details/6776947

    /**
    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则无解...
    **/

      1 //#pragma comment(linker,"/STACK:102400000,102400000")
      2 #include <map>
      3 #include <set>
      4 #include <stack>
      5 #include <queue>
      6 #include <cmath>
      7 #include <ctime>
      8 #include <vector>
      9 #include <cstdio>
     10 #include <cctype>
     11 #include <cstring>
     12 #include <cstdlib>
     13 #include <iostream>
     14 #include <algorithm>
     15 using namespace std;
     16 #define INF 1e8
     17 #define inf (-((LL)1<<40))
     18 #define lson k<<1, L, mid
     19 #define rson k<<1|1, mid+1, R
     20 #define mem0(a) memset(a,0,sizeof(a))
     21 #define mem1(a) memset(a,-1,sizeof(a))
     22 #define mem(a, b) memset(a, b, sizeof(a))
     23 #define FOPENIN(IN) freopen(IN, "r", stdin)
     24 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
     25 template<class T> T CMP_MIN(T a, T b) { return a < b; }
     26 template<class T> T CMP_MAX(T a, T b) { return a > b; }
     27 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
     28 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
     29 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
     30 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
     31 
     32 //typedef __int64 LL;
     33 //typedef long long LL;
     34 const int MAXN = 10005;
     35 const int MAXM = 100005;
     36 const double eps = 1e-10;
     37 //const LL MOD = 1000000007;
     38 
     39 int T, N;
     40 vector<int>v[MAXN];
     41 double k[MAXN], e[MAXN];
     42 double A[MAXN], B[MAXN], C[MAXN];
     43 
     44 
     45 void init()
     46 {
     47     int U, V;
     48     scanf("%d", &N);
     49     for(int i=0;i<=N;i++) v[i].clear();
     50     for(int i=0;i<N-1;i++)
     51     {
     52         scanf("%d %d", &U, &V);
     53         v[U].push_back(V);
     54         v[V].push_back(U);
     55     }
     56     for(int i=1;i<=N;i++)
     57     {
     58         scanf("%d %d", &U, &V);
     59         k[i] = (double)U / 100.0;
     60         e[i] = (double)V / 100.0;
     61     }
     62 }
     63 
     64 bool DFS(int x, int fa)
     65 {
     66     A[x] = k[x];
     67     B[x] = (1 - k[x] - e[x]) / v[x].size();
     68     C[x] = 1 - k[x] - e[x];
     69     if(v[x].size() == 1 && x != fa)
     70         return true;
     71     double temp = 0;
     72     for(int i = 0; i < v[x].size() ; i ++ )
     73     {
     74         int y = v[x][i];
     75         if(y == fa) continue;
     76         if(!DFS(y, x)) return false;
     77         A[x] += A[y] * B[x];
     78         C[x] += C[y] * B[x];
     79         temp += B[y] * B[x];
     80     }
     81     if(fabs(temp - 1.0) < eps) return false;
     82     A[x] = A[x] / (1 - temp);
     83     B[x] = B[x] / (1 - temp);
     84     C[x] = C[x] / (1 - temp);
     85     return true;
     86 }
     87 
     88 int main()
     89 {
     90     //FOPENIN("in.txt");
     91     scanf("%d", &T);
     92     for(int t = 1; t <= T; t ++ )
     93     {
     94         init();
     95         if( DFS(1, 1) && fabs(A[1] - 1.0) > eps )
     96         {
     97             printf("Case %d: %lf
    ", t, C[1] / (1 - A[1]));
     98         }
     99         else
    100         {
    101             printf("Case %d: impossible
    ", t);
    102         }
    103     }
    104 }
  • 相关阅读:
    介绍几个创建GUID的函数
    BOM创建修改(CS01,CS02)保存时增强BADI[BOM_UPDATE]
    REUSE_ALV_GRID_DISPLAY_LVC-双击事件’&IC1′
    REUSE_ALV_GRID_DISPLAY_LVC-行选择功能
    css实现超出部分用...代替
    调用高德地图
    原生验证码 不区分大小写
    原生验证码
    手写验证表单
    获取对象中值的两种方法
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/3888328.html
Copyright © 2011-2022 走看看