ACM: 动态规划题 poj 2057  树状DP

来源:互联网 发布:金山tw域名遭抢注 编辑:程序博客网 时间:2024/06/06 03:03
The LostHouse
Description
One day a snail climbed up to abig tree and finally came to the end of a branch. What a differentfeeling to look down from such a high place he had never been tobefore! However, he was very tired due to the long time ofclimbing, and fell asleep. An unbelievable thing happened when hewoke up ---- he found himself lying in a meadow and his houseoriginally on his back disappeared! Immediately he realized that hefell off the branch when he was sleeping! He was sure that hishouse must still be on the branch he had been sleeping on. Thesnail began to climb the tree again, since he could not livewithout his house.

When reaching the first fork of the tree, he sadly found that hecould not remember the route that he climbed before. In order tofind his lovely house, the snail decided to go to the end of everybranch. It was dangerous to walk without the protection of thehouse, so he wished to search the tree in the best way.

Fortunately, there lived many warm-hearted worms in the tree thatcould accurately tell the snail whether he had ever passed theirplaces or not before he fell off.

Now our job is to help the snail. We pay most of our attention totwo parts of the tree ---- the forks of the branches and the endsof the branches, which we call them key points because key eventsalways happen there, such as choosing a path, getting the help froma worm and arriving at the house he is searching for.

Assume all worms live at key points, and all the branches betweentwo neighboring key points have the same distance of 1. The snailis now at the first fork of the tree.

Our purpose is to find a proper route along which he can find hishouse as soon as possible, through the analysis of the structure ofthe tree and the locations of the worms. The only restriction onthe route is that he must not go down from a fork until he hasreached all the ends grown from this fork.

The house may be left at the end of any branches in an equalprobability. We focus on the mathematical expectation of thedistance the snail has to cover before arriving his house. We wishthe value to be as small as possible.

As illustrated in Figure-1, the snail is at the key point 1 and hishouse is at a certain point among 2, 4 and 5. A worm lives at point3, who can tell the snail whether his house is at one of point 4and 5 or not. Therefore, the snail can choose two strategies. Hecan go to point 2 first. If he cannot find the house there, heshould go back to point 1, and then reaches point 4 (or 5) by point3. If still not, he has to return point 3, then go to point 5 (or4), where he will undoubtedly find his house. In this choice, thesnail covers distances of 1, 4, 6 corresponding to thecircumstances under which the house is located at point 2, 4 (or5), 5 (or 4) respectively. So the expectation value is (1 + 4 + 6)/ 3 = 11 / 3. Obviously, this strategy does not make full use ofthe information from the worm. If the snail goes to point 3 andgets useful information from the worm first, and then chooses to goback to point 1 then towards point 2, or go to point 4 or 5 to takehis chance, the distances he covers will be 2, 3, 4 correspondingto the different locations of the house. In such a strategy, themathematical expectation will be (2 + 3 + 4) / 3 = 3, and it is thevery route along which the snail should search the tree.

ACM: <wbr>动态规划题 <wbr>poj <wbr>2057 <wbr> <wbr>树状DP

Input

The input contains several setsof test data. Each set begins with a line containing one integer N,no more than 1000, which indicates the number of key points in thetree. Then follow N lines describing the N key points. Forconvenience, we number all the key points from 1 to N. The keypoint numbered with 1 is always the first fork of the tree. Othernumbers may be any key points in the tree except the first fork.The i-th line in these N lines describes the key point with numberi. Each line consists of one integer and one uppercase character'Y' or 'N' separated by a single space, which represents the numberof the previous key point and whether there lives a worm ('Y' meanslives and 'N' means not). The previous key point means theneighboring key point in the shortest path between this key pointand the key point numbered 1. In the above illustration, theprevious key point of point 2 or 3 is point 1, while the previouskey point of point 4 or 5 is point 3. This integer is -1 for thekey point 1, means it has no previous key point. You can assume afork has at most eight branches. The first set in the sample inputdescribes the above illustration.

A test case of N = 0 indicates the end of input, and should not beprocessed.

Output

Output one line for each set ofinput data. The line contains one float number with exactly fourdigits after the decimal point, which is the mathematicalexpectation value.

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

题意: 蜗牛要找回自己的家, 但是它忘记路线, 幸运的是每个树杈上会有worm告诉它在当前的树杈上,

     是否看见过它. 它的家是在叶子节点上, 现在要求出回家的最小路程期望值.

 

解题思路:

    1. 一开始看完题目, 存在几个问题:

        (1).例如样例1中的怎么选择2还是选择3节点先访问. 因为选择会影响期望大小.

        (2).如何计算以某一个节点为根的子树, 需要访问的路程长度.

            (在树形结构的数据, 总是要以叶子节点的信息逐步传递给根节点)

     2.设y[x]表示以x为根的子树的叶子节点个数.

         fail[x]表示以x为根的子树没有找到家的路程.

         result[x]表示以x为根的子树成功找到家的路程.

    3. 问题会有几种情况需要更新上面3个数组.

       (1). 当y为叶子节点, x是它的父亲节点时, 在y没有找到家, 当y之后还需要折回到x节点.

            即: fail[x] += fail[y]+2

        (2).计算以x为根的子树, 成功找到家的路程.设yi是x的子节点. 每次计算一个子节点,

            即: 是计算yi之前访问的兄弟节点没有找到家的路程总和.

            得: result[x] += (fail[x]+1)*y[yi]+result[yi]; (i是x的叶子节点的编号)

        (3).最后一个也是最关键, 怎么确定访问顺序会使得期望值小.

            result[x]的大小取决: y[yi]大的先访问, fail[yi]小的先访问.

       (4). 结果 result[1]/y[1]

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
#define MAX 1005

int n;
int num[MAX], flag[MAX];
int g[MAX][MAX];
int y[MAX], fail[MAX], result[MAX];

bool cmp(int u, int v)
{
 return (fail[u]+2)*y[v] <(fail[v]+2)*y[u];
}

void dfs(int u)
{
 if(num[u] == 0)
 {
  result[u] = 0;
  fail[u] = 0;
  y[u] = 1;
  return ;
 }

 int i, v;
 for(i = 0; i < num[u]; ++i)
 {
  dfs(g[u][i]);
  v = g[u][i];
  y[u] += y[v];
 }

 sort(g[u], g[u]+num[u], cmp);
 for(i = 0; i < num[u]; ++i)
 {
  v = g[u][i];
  result[u] += (fail[u]+1)*y[v] +result[v];
  fail[u] += fail[v]+2;
 }
 if(flag[u]) fail[u] = 0;
}

int main()
{
// freopen("input.txt", "r", stdin);
 while(scanf("%d",&n) !=EOF)
 {
  if(n == 0) break;

  memset(num, 0,sizeof(num));
  memset(flag, 0,sizeof(flag));
  memset(y, 0, sizeof(y));
  memset(fail, 0,sizeof(fail));
  memset(result, 0,sizeof(result));

  int x;
  char ch;
  for(int i = 1; i<= n; ++i)
  {
   getchar();
   scanf("%d%c",&x, &ch);
   if(x != -1)g[x][num[x]++] = i;
   if(ch == 'Y')flag[i] = 1;
  }

  dfs(1);
  printf("%.4lf\n",(double)result[1]/y[1]);
 }

 return 0;
}

 

0 0
原创粉丝点击