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!=1return 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;
}




posted on 2009-06-24 20:55 YZY 阅读(1351) 评论(0)  编辑 收藏 引用 所属分类: AlgorithmUSACO动态规划


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


导航

<2009年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

常用链接

留言簿(2)

随笔分类

随笔档案

搜索

积分与排名

最新评论

阅读排行榜