poj 2057 树形DP,数学期望

题目链接:http://poj.org/problem?id=2057

题意:有一只蜗牛爬上树睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面, 现在这只蜗牛要求寻找它的房子,它又得从树根开始爬起,现在要求一条路径使得其找到房子
所要爬行的期望距离最小. 爬行距离如下计算, 题目规定每一个分支和枝末都看做是一个节点, 这些节点之间的距离都是1, 在分支上可能会有热心的毛毛虫, 这些毛毛虫会如实的告诉蜗牛他之前是否经过这条路径, 也正是因为毛毛虫, 因此询问毛毛虫的顺序使得这题的期望是不同的. 输入数据时给定的一个邻接关系,通过上一个节点来构图 ;同时字符 ‘Y‘表示该点有毛毛虫, 字符‘N‘表示该点

分析:

die[i]表示以 i 为根结点找不到房子时要爬行的最少距离。

当 i 没有毛毛虫的时候  j 是 i 的子节点。

当 i 有毛毛虫的时候 ;

win[i]表示以 i 为根结点时,选好所有分支后,枚举完所有房子落在所有叶子结点的时候,要爬的最短距离。

就是说:当我走到 j 而找到时,前面的都失败了。而 j 成功了。j 子树 又有很多叶子结点。其中只有一个是成功的(并不知道是哪个)。

如图:

然后就是对于 i 结点来说,怎么访问才使得重复结点最少。

那就是 

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <cstring>
 6
 7 using namespace std;
 8
 9 const int maxn = 1010;
10 int pos[maxn];
11 int snode[maxn];
12 int die[maxn];
13 int win[maxn];
14 int n;
15
16 vector<int>vec[maxn];
17
18 void init()
19 {
20     memset(pos,0,sizeof(pos));
21     memset(snode,0,sizeof(snode));
22     memset(die,0,sizeof(die));
23     memset(win,0,sizeof(win));
24
25     char ps;
26     int pre;
27     for(int i=1;i<=n;i++) {
28         vec[i].clear();
29     }
30
31     for(int i=1;i<=n;i++) {
32         scanf("%d %c%*c",&pre,&ps);
33         if(pre==-1) continue;
34         vec[pre].push_back(i);
35         if(ps==‘Y‘) pos[i] = 1;
36     }
37 }
38
39 int cmp(int a,int b) {
40     return (die[a]+2)*snode[b]<(die[b]+2)*snode[a];
41 }
42
43 void dfs(int x) {
44     int len  = vec[x].size();
45     for(int i=0;i<len;i++)
46         dfs(vec[x][i]);
47     if(len ==0)
48     {
49         snode[x] = 1;
50         die[x] = 0;
51         win[x] = 0;
52         return;
53     }
54     for(int i=0;i<len;i++) {
55         snode[x] +=snode[vec[x][i]];
56         if(pos[x]==0) die[x] +=die[vec[x][i]] + 2;
57     }
58
59     int tmp[10];
60     for(int i=0;i<len;i++) {
61         tmp[i] = vec[x][i];
62     }
63
64     int sum = 0;
65     sort(tmp,tmp+len,cmp);
66     for(int i=0;i<len;i++) {
67         win[x] +=(sum+1)*snode[tmp[i]] + win[tmp[i]];
68         sum +=die[tmp[i]]+2;
69     }
70
71 }
72
73 int main()
74 {
75     while(scanf("%d%*c",&n),n) {
76         init();
77         double ans;
78         dfs(1);
79         ans = 1.0*win[1]/snode[1];
80         printf("%.4lf\n",ans);
81     }
82     return 0;
83 }

时间: 2024-08-29 01:24:47

poj 2057 树形DP,数学期望的相关文章

poj 3342(树形dp)

题意:在一个公司中要举办一个聚会,每一个员工有一个奉献值.为了和谐规定直接上下级不能一起出席.让你找出奉献值之和最大为多少. 思路:dp[v][1]表示当前结点选,能获得的最大奉献值,dp[v][0]表示当前节点不选能获得的最大奉献值.状态转移: dp[v][0] = max(dp[v][0], ∑max(dp[x][1], dp[x][0]))x为直接儿子 dp[v][1] = max(dp[v][1], ∑dp[x][0] + vex[v]) 最后答案是max(dp[root][0], dp

poj 1947(树形dp)

题意:一棵树上问你最少切掉几条边使得能分割出一个结点数正好为k的子树. 思路:dp[i][j]表示以i为根切掉j个结点最少要几条边. dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 代码如下: 1 dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 2 } 3 } 4 } 5 } 6 } 7 return vex[v]; 8 } 9 10 int main() 11 { 12 // freopen("

POJ 2486 树形DP

有一颗苹果树,每个节点上面有很多苹果,从一个节点到另外一个可以到达的节点花费1步,求k步最多能吃到多少苹果,起始点为1,可以不回到起始点. 这是典型的回溯型树状dp. dp[i][j][0]代表以i为根节点的子树最多j步后回到i能吃到的最多的苹果, dp[i][j][1]代表以i为根节点的子树最多j步后不回到i节点最多能吃到的子树.那么状态转移就分三步了. (1)dp[i][j+2][0] = max(dp[i][j+2][0], dp[i][j-k][0]+dp[son][k][0]); (2

POJ 3342 树形DP入门题

题目意思和POJ2342一样,只是多加了一个条件,如果最大方案数唯一,输出Yes,不唯一输出No dp的是时候多加一个变量记录答案是否唯一即可 #include "stdio.h" #include "string.h" #include "vector" using namespace std; struct node { int fa; vector<int>child; }data[210]; struct comp { int

POJ 1947 树形DP入门题

给出N个点,N-1个关系,建出树形图,问最少减去几个边能得到节点数为P的树.典型树形DP题 dp[cur][j] :记录cur结点,要得到一棵j个节点的子树去掉的最少边数 转移方程用的背包的思想 对当前树的每一个子树进行计算 砍掉此子树:   dp[cur][j]=dp[cur][j]+1; 不砍掉:           for (l=0;l<=j;l++)  dp[cur][j]=Min(dp[cur][j],dp[cur][l]+dp[next][j-l]); 枚举从该树中留l个节点其他由新

POJ 2342 树形DP入门题

有一个大学的庆典晚会,想邀请一些在大学任职的人来参加,每个人有自己的搞笑值,但是现在遇到一个问题就是如果两个人之间有直接的上下级关系,那么他们中只能有一个来参加,求请来一部分人之后,搞笑值的最大是多少. 树形DP入门题. DP部分: dp[i][0]表示职员i不来参加party,以i为根的子树的最大搞笑值, dp[i][1]表示职员i来参加party,以i为根的子树的最大搞笑值. 转移方程: dp[cur][1]+=dp[next][0]; dp[cur][0]+=Max(dp[next][1]

Fire (poj 2152 树形dp)

Fire (poj 2152 树形dp) 给定一棵n个结点的树(1<n<=1000).现在要选择某些点,使得整棵树都被覆盖到.当选择第i个点的时候,可以覆盖和它距离在d[i]之内的结点,同时花费为v[i].问最小花费. 以前做过一道类似的题(水库),这道题也差不多.首先来考虑,用\(best[i]\)表示以i为根的子树的最小花费.这样做有什么问题呢?它无法很好的处理消防站重复建的问题. 所以换一种做法.\(best[i]\)依然表示原来的含义,新建一个数组\(f[i][j]\),表示当i这个结

poj 1655 树形dp求取树的重心

http://poj.org/problem?id=1655 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the large

poj 2342(树形DP)

Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6062   Accepted: 3490 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