hdu 4035 Maze

题意 : 给定一棵树型迷宫,一开始在 1 号节点, 在  第i 个节点 时 有 Ki 的概率被杀死 回到 1 号节点,  Ei 的概率 逃出这个 迷宫 ,  还有 1- Ki -Ei 的概率到达相邻的点,到达相邻的点的概率是相等的, 包括 父亲节点, 。问逃出这个迷宫时 ,走过的树上的路径的期望是多少?


对于 点i

  p = (1 - Ei - Ki )/ m;  m 是 相邻的点的个数。

  E【i 】 =  Ki * E【1】 + p* ( E【 f [ i ] 】+1) + sigma{  p* ( E【son 】+1)  }      :  f[i]为 i的父亲节点   son 为 i节点的孩子 。

化简 得到 : E【 i 】 = Ki * E【1】 + p*  E【 f [ i ] 】+ sigma{  p*  E【son 】  }  + p

每一项 都是 关于 E 【i 】 ,E【f[i]】 和一个常数的式子。

并且: 由孩子的状况 可以推知 父亲的状况。

A[i]   ,  E[1] 的系数 。

B[i]  ,  E[f[i]] 的系数。

C[i]    常数 。

tmp =  p + sigma { p* B[ i ] }

A[ i ]  =( ki  + sigma { p* A[son ]}  ) / (t - tmp);

B[i]  =  p;

C[ i ]  = ( p*m+ sigma { p*C[son ]} ) / (1-tmp);

用 多项式来表示 , 在项数比较小的时候 直接就能推出 ,而不是利用高斯消元。

此题卡精度,  eps = 1e-8 WA  1e-9 AC


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long 
#define pb push_back
const int maxn  = 11000;
int vis[maxn];
int head[maxn];
struct Edge{
    int v;
    int next;
}edge[2*maxn];
int tot;
void init(){
    memset(head,-1,sizeof(head));
    tot = 0;
}
void add(int u,int v){
    tot ++;
    edge[tot].v= v;
    edge[tot].next = head[u];
    head[u] = tot;
}
double a[maxn],b[maxn],c[maxn];
int n;
double  k[maxn],e[maxn];
bool bo;
void dfs(int rt,int f){
    int sum = 0;
    for(int i=head[rt];i!=-1 ;i= edge[i].next){
          sum ++;
    }
    a[rt] = k[rt];
    double p = 1 - k[rt] - e[rt];
    c[rt] = p;
    p /= sum;
    b[rt] = p;
    double fi = 0;
    for(int i=head[rt]; i!= -1;i =edge[i].next){
         int son = edge[i].v;
        if(son ==f)continue;
        dfs(son,rt);
        if(rt ==1){
            a[rt] += p*a[son]+ p*b[son];
            c[rt] += p*c[son];
        }else{
             a[rt] += p*a[son];
             fi +=p*b[son];
             c[rt] += p*c[son];
        }
    }
    if(rt>1){
        if(fabs(fi-1)<eps){
            bo = false;
            return;
        }
       // cout <<fi<<" fi "<< endl;
      a[rt]/= (1 -fi);
      b[rt] /= (1-fi);
      c[rt] /= (1-fi);
    }
   // cout << a[rt] << "  "<<b[rt] << " "<<c[rt] <<endl;
}
void solve(){
        CLEAR(vis);
        bo= true;
        dfs(1,0);
        if(bo){
            if(fabs(a[1]-1)<eps){
               puts("impossible");
               return ;
               
            }
            double ans = c[1] /( 1- a[1]);
            printf("%.6lf\n",ans);
        }else{
            puts("impossible");
        }
}
int main(){
    int t;
    cin>> t;
    int cas = 0 ;
    while(t--){
        cas ++ ;
        printf("Case %d: ",cas);
        scanf("%d",&n);
        init();
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        for(int i=1;i<=n;i++){
             int k1 ,e1;
             scanf("%d%d",&k1,&e1);
             k[i] = (k1+0.0)/100;
             e[i] = (e1+0.0)/100;
        }
        solve();
    }
    return 0;
}


                   








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值