永夜初晗凝碧天

本博客现已全部转移到新地址,欲获取更多精彩文章,请访问http://acshiryu.github.io/

导航

USACO 2.3.2 Cow Pedigrees 解题报告

分类:DP

作者:ACShiryu

时间:2011-7-17

Cow Pedigrees

Silviu Ganceanu -- 2003

Farmer John is considering purchasing a new herd of cows. In this new herd, each mother cow gives birth to two children. The relationships among the cows can easily be represented by one or more binary trees with a total of N (3 <= N < 200) nodes. The trees have these properties:

  • The degree of each node is 0 or 2. The degree is the count of the node's immediate children.
  • The height of the tree is equal to K (1 < K <100). The height is the number of nodes on the longest path from the root to any leaf; a leaf is a node with no children.

How many different possible pedigree structures are there? A pedigree is different if its tree structure differs from that of another pedigree. Output the remainder when the total number of different possible pedigrees is divided by 9901.

PROGRAM NAME: nocows
INPUT FORMAT
  • Line 1: Two space-separated integers, N and K.
SAMPLE INPUT (file nocows.in)
5 3
OUTPUT FORMAT
  • Line 1: One single integer number representing the number of possible pedigrees MODULO 9901.
SAMPLE OUTPUT (file nocows.out)
2
OUTPUT DETAILS

Two possible pedigrees have 5 nodes and height equal to 3:

@                   @      
          / \                 / \
         @   @      and      @   @
        / \                     / \
       @   @                   @   @

题目意思很简单,就是给出NK,找出满足只有N个节点,并且每个节点的度为02,深度为K的二叉树的总数。

很显然可以的得到这个公式 a[i+j+1][max(h1+h2)+1]+=a[i][h1]*a[j][h2];

四个循环就可以解决,求出a[N][K]

但要注意a[i][h1]*a[j][h2]a[j][h2]*a[i][h1]是一样的,所以我们不妨设i>=jh1>=h2;

则可以解决问题

还要注意临界情况,当i=j或者h1=h2出现时

数据分许:时间复杂度为On^2*k^2,题目还可发现当n为偶数时,题目的答案是0又题目中nk的数据不是很大,每次循环都是加2,故应该不会超时

参考代码:

 1 /* 
2 ID:shiryuw1
3 PROG:nocows
4 LANG:C++
5 */
6 #include<iostream>
7 #include<cstdlib>
8 #include<cstdio>
9 #include<cstring>
10 #include<algorithm>
11 #include<cmath>
12 using namespace std;
13 int a[222][111]={0};//表示i个节点构造题目要求的深度为j的二叉树的个数
14 int main()
15 {
16 freopen("nocows.in","r",stdin);
17 freopen("nocows.out","w",stdout);
18 int n,m;
19 int i,j,h1,h2;
20 cin>>n>>m;
21 a[1][1]=1; //1个节点构造深度为一的二叉树只有1中情况
22 for(i=1;i<=n;i+=2)
23 { //i代表左子树的节点数,故要小于n
24 for(j=1;j<=i&&i+j<n;j+=2)
25 { // j代表右子树的节点数,故要i+j<n
26 //又由分析,左右可以交换,故规定j<=i
27 for(h1=1;h1<m;h1++)
28 { //h1表示左子树的深度,可知;h1<m
29 for(h2=1;h2<=h1;h2++)
30 { //h2表示右子树的深度,又左右可以交换,故规定;h2<=h1
31 int ii=i+j+1; //左右子树的节点加上根节点
32 int h=h1+1;//由规定知h1>=h2,故h=max{h1,h2}+1=h1+1
33 if(i==j&&h1==h2)
34 //如果有i=j和h1=h2,则不能交换左右子树
35 a[ii][h]=((a[ii][h]+a[i][h1]*a[j][h2]))%9901;
36 else if(h1==h2||i==j)
37 //当只有h1=h2或i=j时可以交换左右子树的节点数
38 a[ii][h]=(a[ii][h]+2*a[i][h1]*a[j][h2])%9901;
39 else
40 //否则既要交换i和j也要交换左右深度a[ii][h]=(a[ii][h]+2*a[i][h1]*a[j][h2]+2*a[i][h2]*a[j][h1])%9901;
41 }
42 }
43 }
44 }
45 cout<<a[n][m]<<endl; //输出n个节点构造shendu为m的满足条件的二叉树个数
46 return 0;
47 }

  

posted on 2011-07-17 11:24  ACShiryu  阅读(515)  评论(0编辑  收藏  举报