POJ 2057 The Lost House [树状DP]

题意:一只蜗牛将壳忘在了一棵树的某一个末结点(叶子)上。它想找回自己的壳,但忘记是丢在哪个结点上了,只好从树根开始网上爬,一个结点一个结点地找。在一些结点上居住着毛毛虫,它们会告诉蜗牛该结点以及它的子树上是否有它的壳,这样可以节省些时间。两个结点如果相连,则距离为1。问蜗牛找到壳的最小期望距离为多少。

                  

接着给了一个例子(上图):

  假如蜗牛以结点2,4,5的顺序找,则壳分别在结点2,4,5时它需要爬行的距离为1,4,6。则它找到壳的期望为(1 + 4 + 6) / 3 = 11/3。

  考虑另一种情况,假设蜗牛先往结点3的方向爬,而在结点3处有毛毛虫,它可以告诉毛毛虫有关壳的信息,如果壳不在结点3和它的子树上,蜗牛就可以直接调转方向去2了。则以结点4,5,2的遍历顺序来考虑,它需要爬行的距离分别为2, 4, 3,则期望为(2 + 4 + 3) / 3 = 3。该例子中3即为最小期望距离。

思路:

  该题真的很锻炼思维呀,脑细胞死了不少。。

  首先需要用一个leaf[]数组来存储某节点子树上的叶子数,如上图,leaf[1] = 3, leaf[3] = 2。

  此外,对于某结点x,壳只可能有两种状态:在或者不在结点x的子树上。因此,用success[x]表示当壳在结点x的子树上时蜗牛在子树每个叶子上分别找到壳的爬行距离(距离0是从结点x开始算起)之和,如上图,success[3] = 1 + 3;当先访问结点3时,success[1] = 2 + 4 + 3。 这里与上面例子的期望的计算过程对比可以看出,当success表示的值总为最优情况下的距离时,最终期望即为success[1] / leaf[1]。当x为叶子结点时,success[x] = 0。

  当然,我们还要考虑在结点x的子树上找不到壳的情况,用fail[x]表示蜗牛在子树每个叶子上分别没有找到壳时的爬行距离(距离0是从结点x开始算起)之和,该值也应是最优的。最优体现在:如果x处有一只毛毛虫,而且提示x的子树上没有壳时,或者x结点为叶子时,蜗牛便不会再继续前进了,此时fail[x] = 0;否则,蜗牛就只好往前摸索了,此时fail[x] = sum(fail[y] + 2)。其中y是x的儿子结点。还是以上图为例,对于结点3来说,假如此处没有毛毛虫且壳不在3的子树上时,fail[3] = (fail[4] + 2) + (fail[5] + 2)。每个结点都要加2,是因为还要算上折返的距离。比如对于fail[4],蜗牛还要爬过边<3, 4>和<4, 3>,其他结点同理。

  问题的重点是,如何得出每一个点的success值。

  依然是先从简单的开始考虑,先不考虑让success最优。对于结点x,先将它的儿子结点按照遍历顺序从1开始编号,假设目前要遍历的为结点i,则结点1到(i-1)都已经遍历过了,且它们的子树上都没有壳。这里在计算success[x]的同时也在计算fail[x]。每遍历完一个儿子结点y时就有 fail[x] += fail[y] + 2。则当目前要遍历的结点为i时,fail[x]中恰好存储的是访问过结点1到(i-1)且都没有找到壳时的总距离。此时递推公式就比较好理解了:

  success[x] += (fail[x] + 1) * leaf[i] + success[i]。

  需要理解的是,success[i]表示的为结点i子树上找到壳的总距离,该距离是从结点i开始算起的。如果想将该距离转化为以结点x为起点,则需要加上在访问结点i之前走过的总路程,该总路程即为fail[x] + 1。蜗牛找完结点i-1后回到了x,然后从x爬向结点i,这里的加1即为边<x, i>的长度。此外,还需要考虑到结点i的子树上有不止一片叶子,则对于每一片叶子,在访问i之前都爬过了fail[x] + 1的距离,所以需要增加的总距离为(fail[x] + 1) * leaf[i]。

  现在,将最优的前提也考虑进去,则对于结点x,其儿子的访问顺序将会决定是否最优。

  假设x的其中两个儿子为y1, y2。

  如果先y1后y2的顺序遍历到y2,此时有:

  Δsuccess1 = (fail[x] + 1) * leaf[y1] + success[y1] + (fail[x] + fail[y1] + 2 + 1) * leaf[y2] + success[y2];

  如果先y2后y1的顺序遍历到y1,此时有:

  Δsuccess2 = (fail[x] + 1) * leaf[y2] + success[y2] + (fail[x] + fail[y2] + 2 + 1) * leaf[y1] + success[y1];

  Δsuccess1 - Δsuccess2 = (fail[y1] + 2) * leaf[y2] - (fail[y2] + 2) * leaf[y1]。

  这里用到了贪心,对于结点x,如果想让success[x]为最优,则每次遍历时取的儿子结点都应让success[x]的增量为最小。实现的方法是,当访问到结点x时,先用sort函数对x的所有儿子结点排序,排序的规则就是上面那个增量差值的公式,增量小的在前,然后依次遍历,这样得到的success[x]即为最优。

  写了这么多,自己都觉得有些絮叨。这两天脑子昏昏沉沉的,这道题找别人题解看了两天,才渐渐想明白,因此就在这里一点点地分析思路,也是为了帮助向我一样做这题怎么想都想不明白的人吧。

  此外,可能看上面的分析觉得很复杂,但如果看看代码,会觉得简单且好理解不少。有时候看文字解释,真不如读两行代码来得明白。

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<vector>
 4 #include<algorithm>
 5 #include<iostream>
 6 #define maxn 1005
 7 using namespace std;
 8 
 9 int su[maxn], fail[maxn], le[maxn], n, root;
10 bool w[maxn];
11 vector<int> a[maxn];
12 bool cmp(int x,int y)
13 {
14     return (fail[x] + 2) * le[y] < (fail[y] + 2) * le[x];
15 }
16 void dp(int x)
17 {
18     if (a[x].empty())
19     {
20         le[x] = 1;
21         return;
22     }
23     for (int i = 0; i < a[x].size(); i++)
24     {
25         int y = a[x][i];
26         dp(y);
27         le[x] += le[y];
28     }
29     sort(a[x].begin(), a[x].end(), cmp);
30     for (int i = 0; i < a[x].size(); i++)
31     {
32         int y = a[x][i];
33         su[x] += (fail[x] + 1) * le[y] + su[y];
34         fail[x] += fail[y] + 2;
35     }
36     if (w[x]) fail[x] = 0;
37 }
38 int main()
39 {
40     //freopen("data.in", "r", stdin);
41     while (~scanf("%d", &n) && n)
42     {
43         memset(fail, 0, sizeof(fail));
44         memset(su, 0, sizeof(su));
45         memset(le, 0, sizeof(le));
46         memset(w, 0, sizeof(w));
47         for (int i = 1; i <= n; i++)
48             a[i].clear();
49         for (int i = 1; i <= n; i++)
50         {
51             int j;
52             char ch;
53             scanf("%d %c", &j, &ch);
54             if (j == -1) root = i;
55             else a[j].push_back(i);
56             w[i] = (ch == 'Y' ? 1 : 0);//w[i]表示该结点是否有毛毛虫
57         }
58         dp(root);
59         printf("%.4lf\n", 1. * su[root] / le[root]);
60     }
61     return 0;
62 }

 

 

转载于:https://www.cnblogs.com/fenshen371/p/3278673.html

以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化中的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值