hdu4035 Maze 树形dp+期望dp

hdu4035 Maze
传送门
题意
给定一棵树,从\(1\)号节点出发,在每个节点\(i\)有三种可能:
1.以\(k_i\)的概率回到\(1\)号节点
2.以\(e_i\)的概率结束游戏
3.随机走向一个相邻的节点
判断是否可以结束游戏,计算结束时走过边数的期望
题解
\(p_i=1-k_i-e_i\),设从每个节点\(u\)出发的所求期望为\(dp[u]\),则有:
\(dp[u]=k_u*dp[1]+0*e_u+p_u*(\frac{dp[fa]+\sum{dp[v]}}{d_u}+1)\)
也就是
\(dp[u]=k_u*dp[1]+p_u*(\frac{dp[fa]+\sum{dp[v]}}{d_u}+1)\)
其中\(fa\)表示\(u\)的父节点,\(v\)表示\(u\)的子节点,\(d_u\)表示\(u\)的度数
可以将\(dp[u]\)表示成:
\(dp[u]=A_u*dp[fa]+B_u*dp[1]+C_u\)
代入原式,得到:
\(dp[u]=k_u*dp[1]+p_u*(\frac{dp[fa]+\sum{(A_v*dp[u]+B_v*dp[1]+C_v)}}{d_u}+1)\)
整理得到:
\(A_u=\frac{\frac{p_u}{d_u}}{1-\frac{p_u}{d_u}\sum{A_v}}\)
\(B_u=\frac{k_u+\frac{p_u}{d_u}\sum{B_v}}{1-\frac{p_u}{d_u}\sum{A_v}}\)
\(C_u=\frac{p_u+\frac{p_u}{d_u}\sum{C_v}}{1-\frac{p_u}{d_u}\sum{A_v}}\)
通过树形\(dp\)得到\(A[1],B[1],C[1]\),判断从\(1\)号节点是否有可能结束游戏,如果可以结束,那么根据\(dp[1]=A_1*dp[fa]+B_1*dp[1]+C_1\),有\(dp[1]=\frac{C_1}{1-B_1}\)

#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<climits>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;

const int maxn=10010,maxm=20010;
int T,n;
int head[maxn],nxt[maxm],to[maxm],cnt;
int d[maxn];
double k[maxn],e[maxn],p[maxn],A[maxn],B[maxn],C[maxn];

void add(int x,int y){
    to[cnt]=y;
    nxt[cnt]=head[x];
    head[x]=cnt++;
}

void dfs(int u,int fa){
    double a=0.0,b=0.0,c=0.0;
    if(fa) d[u]=1;
    else d[u]=0;
    for(int i=head[u];i!=-1;i=nxt[i]){
        int v=to[i];
        if(v!=fa){
            dfs(v,u);
            a+=A[v];
            b+=B[v];
            c+=C[v];
            d[u]++;
        }
    }
    double t=p[u]/d[u];
    A[u]=t/(1-t*a);
    B[u]=(k[u]+t*b)/(1-t*a);
    C[u]=(p[u]+t*c)/(1-t*a);
}

bool judge(int u,int fa){
    if(e[u]>eps) return true;
    if(p[u]<eps) return false;
    for(int i=head[u];i!=-1;i=nxt[i]){
        int v=to[i];
        if(v!=fa){
            if(judge(v,u)) return true;
        }
    }
    return false;
}

int main(){
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        cnt=0;
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        for(int i=1;i<=n;i++){
            int kk,ee;
            scanf("%d%d",&kk,&ee);
            k[i]=1.0*kk/100;
            e[i]=1.0*ee/100;
            p[i]=1.0*(100-kk-ee)/100;
        }
        dfs(1,0);
        printf("Case %d: ",cas);
        if(!judge(1,0)) printf("impossible\n");
        else printf("%.6f\n",C[1]/(1-B[1]));
    }
    return 0;
}
posted @ 2020-08-15 16:55  fxq1304  阅读(51)  评论(0编辑  收藏  举报