POJ 2057 The Lost Home 树形dp 难度:2
| Time Limit: 3000MS | Memory Limit: 30000K | |
| Total Submissions: 2203 | Accepted: 906 |
Description
When reaching the first fork of the tree, he sadly found that he could not remember the route that he climbed before. In order to find his lovely house, the snail decided to go to the end of every branch. It was dangerous to walk without the protection of the house, so he wished to search the tree in the best way.
Fortunately, there lived many warm-hearted worms in the tree that could accurately tell the snail whether he had ever passed their places or not before he fell off.
Now our job is to help the snail. We pay most of our attention to two parts of the tree ---- the forks of the branches and the ends of the branches, which we call them key points because key events always happen there, such as choosing a path, getting the help from a worm and arriving at the house he is searching for.
Assume all worms live at key points, and all the branches between two neighboring key points have the same distance of 1. The snail is now at the first fork of the tree.
Our purpose is to find a proper route along which he can find his house as soon as possible, through the analysis of the structure of the tree and the locations of the worms. The only restriction on the route is that he must not go down from a fork until he has reached all the ends grown from this fork.
The house may be left at the end of any branches in an equal probability. We focus on the mathematical expectation of the distance the snail has to cover before arriving his house. We wish the value to be as small as possible.
As illustrated in Figure-1, the snail is at the key point 1 and his house is at a certain point among 2, 4 and 5. A worm lives at point 3, who can tell the snail whether his house is at one of point 4 and 5 or not. Therefore, the snail can choose two strategies. He can go to point 2 first. If he cannot find the house there, he should go back to point 1, and then reaches point 4 (or 5) by point 3. If still not, he has to return point 3, then go to point 5 (or 4), where he will undoubtedly find his house. In this choice, the snail covers distances of 1, 4, 6 corresponding to the circumstances under which the house is located at point 2, 4 (or 5), 5 (or 4) respectively. So the expectation value is (1 + 4 + 6) / 3 = 11 / 3. Obviously, this strategy does not make full use of the information from the worm. If the snail goes to point 3 and gets useful information from the worm first, and then chooses to go back to point 1 then towards point 2, or go to point 4 or 5 to take his chance, the distances he covers will be 2, 3, 4 corresponding to the different locations of the house. In such a strategy, the mathematical expectation will be (2 + 3 + 4) / 3 = 3, and it is the very route along which the snail should search the tree.

Input
A test case of N = 0 indicates the end of input, and should not be processed.
Output
Sample Input
5
-1 N
1 N
1 Y
3 N
3 N
10
-1 N
1 Y
1 N
2 N
2 N
2 N
3 N
3 Y
8 N
8 N
6
-1 N
1 N
1 Y
1 N
3 N
3 N
0
Sample Output
3.0000
5.0000
3.5000
题意:有一只蜗牛丢了壳现在要爬树找回来,这棵树上有些地方有善良的虫子告诉它,它的壳是不是在这枝桠上,现在不知道壳在哪个叶节点上,问怎么选择走的顺序,平均长度期望最小,输出平均长度期望
思路:
0.1 看到这个期望,必须发现的是过程只要不除以叶节点数就可以过程中不出现浮点数,只计算某种最优路径选择,使得分别到达各点的所需长度之和最短即可,
0.2 首先看去掉虫子的影响来看这棵树,我们知道树的问题的一大特点就是把整棵树换成各子树和根节点之间的某种运算
1 怎么样把走多次树变成走一次树呢?(如果要是走n次铁定就超时了),仔细看看树,如果选择先走某枝桠,这棵树上的叶节点有两种可能,A:在这个枝桠上,B:不在这个枝桠上,
B:当我们选择了先走这棵枝桠的时候就必须走一遍这棵枝桠的每一个节点,(假设没虫)于是我们设这个长度为bak(back)[i],对于子节点j,bak[i]=sigma(bak[j]+2)
A:不断重复选择先走那一只子节点,一直走到叶节点为止,所花费的时间是之前走过的无用枝桠长度(+从根节点到达那些子节点的长度)+到达这个叶节点不返回的长度,可是这个只对于叶节点有意义,对于非叶节点,我们设scan[i]为遍历到所有它的子叶节点,从i点出发的所有路径长度之总和(的最小值),设i的子节点为j,k,j是现在要走的节点,k是已经走过的节点,scan[i]=sigma(lef[j]*(1(出发到子节点的步数+sigma(bak[k]+2)(前面多走的路+往返这些子节点))+scan[j](遍历这些j上的子节点))
对于叶节点,明显bak[i]=scan[i]=0 2 现在算是有确定了遍历顺序时的计算公式了,可是怎么确定遍历子节点的顺序呢?对于外部,只有scan[i]重要,所以子节点的顺序要使scan[i]最小,排列的话肯定超时,只能用贪心了
任取两个节点j1,j2,假设j1在j2前面的scan[i]=S1,j2在j1前面的scan[i]=S2,S1-S2=(lef[j1]*(bak[j2]+2)-lef[j2]*(bak[j1]+2)),整理一下,要让这个值小于零,应该有lef[j1]/(bak[j1]+2)小于lef[j2]/(bak[j2]+2),这时候j1更优,显然按这个值增序排序就可以确定选取顺序了 3 现在加上虫子的影响,如果有虫的话虫子会告诉蜗牛不用经过这个点,也即bak[i]=0 错误次数:5
原因: 1 bak[s]+=bak[son]+2;忘了+2,测试数据太弱没测出来 2 double ans=(double)scan[1]/(double )lef[1];直接除以lef了 3 lef没有memset 4 弃疗随便交
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=1002;
long long scan[maxn],bak[maxn];
int lef[maxn];
bool worm[maxn];
int len[maxn];
int e[maxn][maxn];
int n;
char buff[2];
typedef pair<double,int> P;
void dfs(int s){
if(len[s]==0){
scan[s]=bak[s]=0;
lef[s]=1;
return ;
}
priority_queue<P,vector<P>,greater<P> >que;
for(int i=0;i<len[s];i++){
dfs(e[s][i]);
lef[s]+=lef[e[s][i]];
}
for(int i=0;i<len[s];i++){
que.push(P((double)(bak[e[s][i]]+2)/(double )lef[e[s][i]],e[s][i]));
}
int son,sum=0;
for(int i=1;!que.empty();i++){
long long tmp=que.top().first;
son=que.top().second;que.pop();
sum+=lef[son];
scan[s]+=scan[son]+lef[son]+(2+bak[son])*(lef[s]-sum);
bak[s]+=bak[son]+2;
}
if(worm[s]) bak[s]=0;
} int main(){
while(scanf("%d",&n)==1&&n){
memset(len,0,sizeof(len));
memset(worm,0,sizeof(worm));
memset(scan,0,sizeof(scan));
memset(bak,0,sizeof(bak));
memset(lef,0,sizeof(lef));
for(int i=1;i<=n;i++){
int f;
scanf("%d%s",&f,buff);
if(f>0){
e[f][len[f]++]=i;
}
if(buff[0]=='Y')worm[i]=true;
}
dfs(1);
double ans=(double)scan[1]/(double )lef[1];
printf("%.4f\n",ans);
}
return 0;
}
POJ 2057 The Lost Home 树形dp 难度:2的更多相关文章
- POJ 3140.Contestants Division 基础树形dp
Contestants Division Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10704 Accepted: ...
- POJ:2342-Anniversary party(树形dp入门题目)
传送门:http://poj.org/problem?id=2342 Anniversary party Time Limit: 1000MS Memory Limit: 65536K Descrip ...
- 树的点分治 (poj 1741, 1655(树形dp))
poj 1655:http://poj.org/problem?id=1655 题意: 给无根树, 找出以一节点为根, 使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子 ...
- poj 2342 Anniversary party 简单树形dp
Anniversary party Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3862 Accepted: 2171 ...
- POJ 1155 TELE 背包型树形DP 经典题
由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送 ...
- poj 3140 Contestants Division(树形dp? dfs计数+枚举)
本文出自 http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...
- POJ 3140 Contestants Division 【树形DP】
<题目链接> 题目大意:给你一棵树,让你找一条边,使得该边的两个端点所对应的两颗子树权值和相差最小,求最小的权值差. 解题分析: 比较基础的树形DP. #include <cstdi ...
- UVa 10859 - Placing Lampposts 树形DP 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- Uva LA 3902 - Network 树形DP 难度: 0
题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...
随机推荐
- MIME协议(详解范例)
转载一:http://blog.csdn.net/bripengandre/article/details/2192982 转载二:http://blog.csdn.net/flfna/article ...
- cogs 362. [CEOI2004]锯木厂选址
★★★ 输入文件:two.in 输出文件:two.out 简单对比 时间限制:0.1 s 内存限制:32 MB 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来. ...
- 切面条|2014年蓝桥杯B组题解析第二题-fishers
切面条 一根高筋拉面,中间切一刀,可以得到2根面条. 如果先对折1次,中间切一刀,可以得到3根面条. 如果连续对折2次,中间切一刀,可以得到5根面条. 那么,连续对折10次,中间切一刀,会得到多少面条 ...
- Unity 之 Vector3
class Variables one 指向(0,0,0) zero 指向(1,1,1) right指向 x轴的方向 Up 指向 y轴的方向 forward 指向 z轴的方向
- Linux CentOS 7 下 JDK 安装与配置
前言 简单记录一下在CentOS 7中安装配置JDK 1.7的全过程~ ( 安装别的版本或者jre一样) 下载 首先是jdk 1.7 64bit & 32bit的下载地址: jdk-7u79 ...
- Unity3D学习笔记(十六):Animator新动画
新动画系统: 给模型选择动画类型 普通动画:Generic 人形动画:Humanoid 建立动画控制器 - 在Project右击 - 选择Create-AnimatorContorller 将对应动画 ...
- Leetcode[1]Two Sum C++
最简单的思想,遍历, 1.两层循环,自己写的,没有用STL,时间花费较长 vector<int> twoSum(vector<int>& nums, int targe ...
- java编程内容之开始
java应用程序开发应该掌握的各方面技术 1.初识java,熟悉Eclipse开发工具 2.java语言基础 3.流程控制,数组,字符串,类与对象 4.接口,继承与多态,类的高级特性 5.Java集合 ...
- hdu 1427 速算24点 dfs暴力搜索
速算24点 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem De ...
- poj 2186 Popular Cows tarjan
Popular Cows Description Every cow's dream is to become the most popular cow in the herd. In a herd ...