poj2057--The Lost House(树状dp,求期望)

题目链接:点击打开链接

题目大意:蜗牛把壳落在了一个树梢上,壳在每一个树梢上的概率是相同的。现在他从树根开始爬,在树杈中可能会有毛毛虫,告诉它壳是否在这个树枝上。每个树枝的长度为1,问最终能找到壳需要爬行的距离期望值最小是多少。

求期望值 = ∑到第i个树梢的距离*在第i个树梢上的概率(i为叶子节点) = 到所有叶子节点的和/叶子节点数。也就是说要求一个序列,按这个序列到达每一个节点的和是最小的。

现在需要判断的就是怎么找到这一个序列,也就是在分叉中如何判断先走哪个叉。

假设根为s,有两个叉为a和b,那么如果壳在s上,有两种可能:

先走a,后走b。

期望值 = 在a上找到壳的期望*壳在a的概率 + (由a返回s的步数+在b上找到壳的期望)*壳在b的概率

先走b,后走a。

期望值 = 在b上找到壳的期望*壳在b的概率 + (由b返回s的步数+在a上找到壳的期望)*壳在a的概率

这两种方式的区别在于 第一个 有一个k1 =(有a返回s的步数*壳在b的概率)。第二个有k2=(在b返回s的步数*壳在a的概率)。如果要求期望值最小。那么就是找到k1和k2中小的一种方式,这样就得到两个叉之间的排序关系,也就可以找出任意几个叉访问的序列,就可以得出最终的序列。

三个数组:

re存储由子节点返回父节点的步数(受到re[子节点]和是否有毛毛虫的控制)

num:(如果壳在这个子树上的)存储该节点需要的平均期望

p:存储壳在该子树上的概率,为计算方便统一乘以总节点数。

re[s] = ∑(re[i])+2 或者 re[s] = 2;

num[s] = 按顺序得到期望值/叶子节点数

p[s] = ∑(p[i])

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define eqs 1e-8
struct node{
    int u , v ;
    int next ;
}edge[1010] , temp[1010] ;
int head[1010] , cnt ;
double re[1010] , num[1010] , p[1010] ;
int k[1010] ;
void add(int u,int v) {
    edge[cnt].u = u ; edge[cnt].v = v ;
    edge[cnt].next = head[u] ; head[u] = cnt++ ;
}
int cmp(node a,node b) {
    return re[ b.v ]*p[ a.v ] - re[ a.v ]*p[ b.v ] > eqs  ;
}
void dfs(int u) {
    re[u] = num[u] = p[u] = 0 ;
    if( head[u] == -1 ) {
        re[u] = 2 ;
        num[u] = 1 ;
        p[u] = 1 ;
        return ;
    }
    int i , j = 0 , v , s ;
    for(i = head[u] ; i != -1 ; i = edge[i].next) {
        dfs(edge[i].v) ;
    }
    for(i = head[u] ; i != -1 ; i = edge[i].next) {
        temp[j++] = edge[i] ;
        p[u] += p[edge[i].v] ;
        re[u] += re[ edge[i].v ] ;
    }
    if( k[u] ) re[u] = 0 ;
    re[u] += 2 ;
    sort(temp,temp+j,cmp) ;
    for(i = 0 , s = 0 , num[u] = p[u] ; i < j ; i++) {
        num[u] += (s+num[ temp[i].v ])*p[ temp[i].v ] ;
        s += re[ temp[i].v ] ;
    }
    num[u] /= p[u] ;
    return ;
}
int main() {
    int n , i , u , v ;
    char s[10] ;
    while( scanf("%d", &n) && n ) {
        memset(head,-1,sizeof(head)) ;
        memset(k,0,sizeof(k)) ;
        cnt = 0 ;
        for(i = 1 ; i <= n ; i++) {
            scanf("%d %s", &u, s) ;
            if( s[0] == 'Y' ) k[i] = 1 ;
            if(u == -1) u = 0 ;
            add(u,i) ;
        }
        dfs(1) ;
        printf("%.4f\n", num[1]-1.0) ;
    }
    return 0 ;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 03:43:17

poj2057--The Lost House(树状dp,求期望)的相关文章

HDU 2196 树状dp 求树中节点之间的最长距离

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3749    Accepted Submission(s): 1892 Problem Description A school bought the first computer some time ago(so this computer's id is 1). Du

POJ 1463 树状dp

Strategic game Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 6629   Accepted: 3058 Description Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad

POJ 2342 树状dp

Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4606   Accepted: 2615 Description There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure

洛谷P2015 二叉苹果树(树状dp)

题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=100). N表示树

树状DP入门

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题目大意:给定一棵关系树,每个节点有个权值,子节点和父节点不能同时选,问最后能选的最大价值是多少? 解题思路:树形DP入门题.由于子节点与父节点不能同时选,有人可能会用贪心思想,二者选其一肯定最优.其实不然,有可能父节点和子节点都不选,而要选子孙节点.不过只要再往深点想下,就可以得出动态规划的解法.每个节点要么选要么不选,和大多数选不选动归一样,来个dp[i][2],0表示不选,1表示不选,那

树状DP (poj 2342)

题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[i][0] += max(F[k][1], F[k][0]);(k为i的儿子) 第二种情况:第i个员工参与,F[i][1] += F[k][0]; F[i][j]表示第i个员工是否参与: 边界:F[i][0] = 0:F[i][1] = 其快乐指数: #include <iostream> #in

ZOJ-2386 Ultra-QuickSort 【树状数组求逆序数+离散化】

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input seque

POJ2985 The k-th Largest Group[树状数组求第k大值 并查集]

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted: 2875 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

树状数组求逆序对

给定n个数,要求这些数构成的逆序对的个数.除了用归并排序来求逆序对个数,还可以使用树状数组来求解.树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0.从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了.把所有的加起来就是总的逆序对数.题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000.如果采用上面的思想,必然会导致空间的巨大浪费,而且由

树状数组求区间最值

树状数组求区间最值 树状数组(Binary Index Tree)利用二进制的一些性质巧妙的划分区间,是一种编程,时间和空间上都十分理想的求区间和的算法,同样我们可以利用树状数组优美的区间划分方法来求一个序列的最值 约定以 num[]  表示原数组, 以 idx[] 表示索引数组, Lowbit(x)=x&(-x) 树状数组求和时通过构造数组 idx[] 使 idx[k]=sum(num[tk]), tk [k-Lowbit(k)+1,k], 使用同样的方法构造最值索引数组: 以最大值为例, 先