zoukankan      html  css  js  c++  java
  • CF643E Bear and Destroying Subtrees (期望DP)

    洛谷:题目链接
    首先要确认这是一个期望DP.
    线性性质就不必说了.
    设f[x][i]表示以x为根,(dep[x_{son}] <= h)的概率
    那么答案就是.(sum_{h = 1}^{MAX\_H}h * (f[x][h] - f[x][h - 1]))
    考虑如何更新.
    显然,可以通过(x_{son})转移,那么子节点(v = son_x)有两种情况,一个是存在边,对(f[x][h])贡献(1/2 * f[v][h - 1])的概率,二十不存在该边,概率那么就是(1/2)
    然后就成了(f[x][h] = prod_{v = son_x}(1/2 + 1/2 * f[v][h - 1]))
    更新的时候暴力更新即可,一直往上直到根节点.除掉以前的项,乘上新的项即可.
    但是如果深度特别大怎么办,注意题目中的有精度误差,那么到了很大的数就会比(1e-6)小,这个时候精度达到了,不用继续.这里选择取(Max\_H = 60).
    CODE

    #include <iostream>
    #include <cstdio>
    const int maxN = 5e5 + 7;
    const int maxH = 60;
    
    int n,fa[maxN];
    double f[maxN][maxH];
    
    inline int read() {
    	int x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9' ) {if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    	return x * f;
    }
    
    int main() {
    	int n = 1,T = read(),opt,x;
    	for(int i = 0;i < maxH;++ i) f[1][i] = 1;
    	while(T --) {
    		opt = read();x = read();
    		if(opt == 1) {
    			fa[++ n] = x;
    			for(int i = 0;i < maxH;++ i) 
    				f[n][i] = 1;
    			double tmp1 = f[x][0],tmp2;
    			f[x][0] *= 0.5;
    			for(int Fa = fa[x],i = 1; Fa && i < maxH; Fa = fa[x = Fa],++ i)
                {
                    tmp2 = f[Fa][i];
                    f[Fa][i] /= 0.5 + 0.5 * tmp1;
                    f[Fa][i] *= 0.5 + 0.5 * f[x][i-1];
                    tmp1 = tmp2;
            	}
    		}
    		else {
    			double ans = 0;
    			for(int i = 1;i < maxH;++ i) 
    			ans += (f[x][i] - f[x][i - 1]) * i;
    			printf("%.10lf
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    新年新气象,用新年的喜庆来迎接的生活
    vs2005中如何发布网站及打包web项目生成安装文件
    完整打印页面控件的解决方案
    vi使用体会
    向ATL DLL中传递C++对象
    CentOS 5.3配置软件源以及CVS服务器
    堆上多维数组的内存管理
    物理坐标与逻辑坐标
    好友列表的实现
    在STL中处理对象指针
  • 原文地址:https://www.cnblogs.com/tpgzy/p/9691360.html
Copyright © 2011-2022 走看看