pku 1241 Knockout Tournament 树形DP,很好的题目

题意:

看图说话,一棵锦标赛树(具体不描述,看DS书去),问每个队员的最好名次和最坏名次

分析:
求最好名次应该从上向下划分状态,而求最坏名次从下向上划分状态,举个例子吧,看第三排第一个1,它的最坏名次是第四排第一个1的最坏名次加上它的1^n-右孩子的最坏名次-1,而它的最好名次则是第二排第一个1的最好名次,它旁边那个3的最好名次就是3的父节点(1)的最好名次+1,大概明白什么意思了吧?看代码吧~。

代码:
 1 # include <cstdio>
 2 # include <cstring>
 3 using namespace std;
 4 # define max(a,b) ((a)>(b)?(a):(b))
 5 # define min(a,b) ((a)<(b)?(a):(b))
 6 int tree[1024],n;
 7 int worst[1024],best[1024],high[1024],low[1024];
 8 int main()
 9 {
10     while(true)
11     {
12         scanf("%d",&n);
13         if(!n) break;
14         for(int i=1<<n;i<1<<(n+1);i++)
15             tree[i]=1+i-(1<<n),worst[i]=1<<n;
16         for(int t=n-1;t>=0;t--)
17             for(int i=1<<t;i<1<<(t+1);i++)
18             {
19                  scanf("%d",tree+i);
20                  worst[i]=(tree[i]==tree[i<<1]?worst[i<<1]-(1<<n)+worst[(i<<1)+1]:worst[(i<<1)+1]-(1<<n)+worst[i<<1])-1;
21             }
22         best[1]=1;
23         for(int i=2;i<1<<(n+1);i++)
24             best[i]=(tree[i]==tree[i>>1]?best[i>>1]:best[i>>1]+1);
25         for(int i=1;i<1<<(n+1);i++)
26             high[i]=low[i]=1<<n;
27         for(int i=1;i<1<<(n+1);i++)
28         {
29             high[tree[i]]=min(high[tree[i]],best[i]);
30             low[tree[i]]=min(low[tree[i]],worst[i]);
31         }
32         scanf("%d",&n);
33         while(n--)
34         {
35             int t;
36             scanf("%d",&t);
37             printf("Player %d can be ranked as high as %d or as low as %d.\n",t,high[t],low[t]);
38         }
39         printf("\n");
40     }
41     return 0;
42 }


posted on 2011-01-20 01:44 yzhw 阅读(289) 评论(0)  编辑 收藏 引用 所属分类: DPdata struct


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年1月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜