USACO 2.3 Cow Pedigrees

USACO 2.3 Cow Pedigrees


用memoization dp解。
用dp[n][k]来记录结点数为n,高度<=k的树的形态的个数。
由于树的结点的度数只可能为0或2,这个树的结点总数必然是个奇数。(推导很简单,一般数据结构书都会有,略)
树的高度最高为(n-1)/2。
dp[n][k]= dp[1][k-1]*dp[n-2][k-1]+dp[2][k-1]*dp[n-3][k-1]+...+dp[n-2][k-1]*dp[1][k-1];
利用对称性质,可以节省一半计算。
dp[1][1]是递归的出口。

有了dp[n][k]了,求高度恰好等于k的树的形态的个数就很显然dp[n][k]-dp[n][k-1]可得。
由于要模上9901,注意可能是负值,所以要先加上9901再求模。

代码如下:

#include  < iostream >
#include 
< fstream >

using   namespace  std;

ifstream fin(
" nocows.in " );
ofstream fout(
" nocows.out " );

int  dp[ 200 ][ 100 ];
int  n,k;

int  ped_num( int  node, int  height);

void  solve()
{
    memset(dp,
- 1 , sizeof (dp));

    dp[
1 ][ 1 =   1 ;

    
in >> n >> k;

    
out << (ped_num(n,k) - ped_num(n,k - 1 ) + 9901 ) % 9901 << endl;
}

int  ped_num( int  node, int  height)
{
    
if (node % 2 != 1 return   0 ;

    
if (height > (node + 1 ) / 2 )
        height 
=  (node + 1 ) / 2 ;

    
if (dp[node][height] !=- 1 )
        
return  dp[node][height];

    
int  res  =   0 ;

    
for ( int  i = 1 ;i < (node - 1 ) / 2 ;i += 2 ){
        res
+= ped_num(i,height - 1 ) * ped_num(node - 1 - i,height - 1 );
        res
%= 9901 ;
    }
    res
*= 2 ;
    
int  tmp  =  ped_num((node - 1 ) / 2 ,height - 1 );
    res
+= tmp * tmp;
    res
%= 9901 ;

    dp[node][height] 
=  res;
    
return  res;
}

int  main( int  argc, char   * argv[])
{
    solve(); 
    
return   0 ;
}




你可能感兴趣的:(USACO 2.3 Cow Pedigrees)