zoukankan      html  css  js  c++  java
  • POJ 2057

    设一棵树有两个子树A,B。Pa是房子在A子树上的概率,Pb是房子在B子树上的概率。

    先走A子树寻找房子的期望是:

    【在A子树上找到房子的路程】*Pa+(【没有在A子树上找到房子的路程(固定的一个值)】+【在B子树上找到房子的路程】)*Pb。  

    先走B子树寻找房子的期望是:

    【在B子树上找到房子的路程】*Pb+(【没有在B子树上找到房子的路程(固定的一个值)】+【在A子树上找到房子的路程】)*Pa。

    若这两个值做比较的话,可以化简为:

    【没有在A子树上找到房子的路程(固定的一个值)】*Pb【没有在B子树上找到房子的路程(固定的一个值)】*Pa相比较。

    Pa=(A子树上的叶子节点数)/(所有的叶子节点数);Pb也是如此。

    通过排序就可以设计出在树上的寻找路径了。

    ——引用来自http://blog.csdn.net/lin375691011/article/details/31446343

    当然,由于所有的叶子结点数目是固定的,所以可以直接用A子树上的叶子节点数代替Pa,类似的Pb也是如此。

    对于表示u为根的子树上,找不到房子的步数和dp[u][0]=∑(dp[v][0]+2)  ( (u,v)是一条边,因为是没找到,所以永远都要从哪里出发就回到那里,所以每多一层,就多一次去加一次来 )

     (真的是一道非常不错的题目,值得深究)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define MAXN 1005
     5 using namespace std;
     6 int n,num[MAXN],dp[MAXN][2],head[MAXN];
     7 //dp[u][1]:表示u为根的子树上,成功找到房子的步数和 
     8 //dp[u][0]:表示u为根的子树上,找不到房子的步数和 
     9 //head[u]:第一条以u为头节点的边
    10 bool worm[1005];
    11 struct Edge{
    12     int u,v,adj;//起点、终点、同起点的邻边 
    13 }edge[MAXN];
    14 bool cmp(int a,int b)
    15 {
    16     return( (dp[a][0]+2)*num[b] < (dp[b][0]+2)*num[a] );
    17 }
    18 void dfs(int st)
    19 {
    20     int p=head[st];
    21     dp[st][0]=0;
    22     dp[st][1]=0;
    23     num[st]=0;
    24     if(p==-1) num[st]++;//作为根,本身就是叶子结点 
    25     else
    26     {
    27         int cnt=0,group[10];
    28         while(p!=-1)
    29         {
    30             dfs(edge[p].v);
    31             dp[st][0]+=dp[(edge[p].v)][0]+2;
    32             num[st]+=num[edge[p].v];
    33             group[cnt++]=edge[p].v;
    34             p=edge[p].adj;
    35         }
    36         if(worm[st]) dp[st][0]=0;//如果有worm帮忙,知道这里从这里往下不用再找了,没有房子,就不用跑 
    37         sort(group,group+cnt,cmp);
    38         int tmp=0;
    39         for(int i=0;i<cnt;i++)//i表示在第i棵子树下有房子 
    40         {
    41             dp[st][1]+=dp[group[i]][1]+(tmp+1)*num[group[i]];
    42             tmp+=dp[group[i]][0]+2;//走了i子树,没有找到,返回到st 
    43         }//这一段for语句非常漂亮,属于解本题的核心思路
    44     } 
    45     //printf("point %d: dp[][0]=%d dp[][1]=%d
    ",st,dp[st][0],dp[st][1]);
    46 }
    47 int main()
    48 {
    49     while(scanf("%d",&n) && n!=0)
    50     {
    51         memset(head,-1,sizeof(head));
    52         int from,cnt=1;
    53         char tmp[5];
    54         scanf("%d%s",&from,tmp);
    55         for(int i=2;i<=n;i++)
    56         {
    57             scanf("%d%s",&from,tmp);
    58             worm[i]=(tmp[0]=='Y'?1:0);
    59             edge[cnt].u=from; 
    60             edge[cnt].v=i;
    61             edge[cnt].adj=head[from];
    62             head[from]=cnt;
    63             cnt++;
    64         }
    65         /*
    66         for(int i=1;i<=n-1;i++) printf("edge %d: from=%d to=%d adj=edge%d
    ",i,edge[i].u,edge[i].v,edge[i].adj);
    67         for(int i=1;i<=n;i++) printf("head %d: edge %d
    ",i,head[i]); //检查边是否存储正确 
    68         for(int i=2;i<=n;i++) printf("point %d: worm %s
    ",i,worm[i]?"exist":"not exist"); //检查worm是否存储正确
    69         */
    70         dfs(1); 
    71         printf("%.4f
    ", ((double)dp[1][1])/((double)num[1]) );
    72     }
    73 }

    另外,请注意http://poj.org/showmessage?message_id=341806,这影响到输入时的数据存储方式,之前我是按照:边是按顺序一层层下来的,就一直WA

  • 相关阅读:
    ViewData,ViewBag,TempData
    http和https
    Array与ArrayList
    程序员与书和视频
    技术学习的方法研究
    文章发布声明
    面向对象JAVA多态性
    嵌入式开发总结
    CSDN博客代码显示乱码的原因
    将Windows的桌面目录设置到D盘
  • 原文地址:https://www.cnblogs.com/dilthey/p/7017128.html
Copyright © 2011-2022 走看看