USACO-Section2.3 Cow Pedigrees【动态规划】

2024-04-12 06:38

本文主要是介绍USACO-Section2.3 Cow Pedigrees【动态规划】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述:

农民John准备购买一群新奶牛。 在这个新的奶牛群中, 每一个母亲奶牛都生两个小奶牛。这些奶牛间的关系可以用二叉树来表示。这些二叉树总共有N个节点(3 <= N < 200)。这些二叉树有如下性质:
每一个节点的度是0或2。度是这个节点的孩子的数目。
树的高度等于K(1 < K < 100)。高度是从根到最远的那个叶子所需要经过的结点数; 叶子是指没有孩子的节点。
有多少不同的家谱结构? 如果一个家谱的树结构不同于另一个的, 那么这两个家谱就是不同的。输出可能的家谱树的个数除以9901的余数。(翻译来源:NOCOW)

INPUT FORMAT

第1行: 两个空格分开的整数, N和K。

OUTPUT FORMAT

第1行: 一个整数,表示可能的家谱树的个数除以9901的余数。


SAMPLE INPUT

5 3


SAMPLE OUTPUT

2


OUTPUT DETAILS

有5个节点,高为3的两个不同的家谱:

     @                                 @/ \                               / \@   @            和               @   @/ \                                   / \@   @                                 @   @

解题思路:

这道题困扰了我许久。我一直在想如何用树的知识来解决此问题,然后在考虑如何通过二叉树的特性来解决,一开始考虑的是递归循环,通过深搜来得出所有结果,从而判断是否可以得出结果,但是这样做的话时间是指数级的,想了想就放弃了,而且总感觉有其他好方法。然后,在晚上浏览了一下nocow官方的解法,发现真的是神奇。说实话,这种方法并不难理解而且很形象(例如一颗深度为4的树可以由两棵深度为3的树组成,也可以由一棵深度为2或1和一棵深度为3的树组成,只要节点数量对即可,当然,深度为3的树是必须的),但是将一棵二叉树看成两棵子树的和这种动归的思路之前从未考虑过,感到了震撼Orz。官方解释的已经很全面了,下面是代码。


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define MOD 9901
int table[101][202],N,K,c;//table数组用来保存产生第i行第j个节点可能的个数,N为节点个数,K为树的深度,c用来判断数的结构 
int smalltrees[101][202];//保存深度小于i-1且节点数为j的树的个数 int main() {    FILE *fin=fopen("nocows.in","r");FILE *fout=fopen("nocows.out","w");   fscanf (fin,"%d %d",&N,&K);table[1][1]=1;for (int i=2;i<=K;i++) {for (int j=1;j<=N;j+=2)for (int k=1;k<=j-1-k;k+=2) {if (k!=j-1-k) c=2; else c=1;  //判断树的结构是否对称  table[i][j]+=c*(smalltrees[i-2][k]*table[i-1][j-1-k]  // 左子树深度小于i-1+table[i-1][k]*smalltrees[i-2][j-1-k]  // 右子树深度小于i-1+table[i-1][k]*table[i-1][j-1-k]);// 都为i-1table[i][j]%=MOD;}for (int k=0;k<=N;k++) { // 确保接下来第i次迭代中的smalltrees[i-2][j]包含了深度小于i-1且节点数为j的树的个数smalltrees[i-1][k]+=table[i-1][k]+smalltrees[i-2][k]; smalltrees[i-1][k]%=MOD; }}fprintf (fout,"%d\n",table[K][N]);return 0;
}

这篇关于USACO-Section2.3 Cow Pedigrees【动态规划】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/896384

相关文章

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

usaco 1.3 Calf Flac(暴搜)

思路是暴搜。 需要注意的地方是输入的方法,以及输出时的换行。 代码: /*ID: who jayLANG: C++TASK: calfflac*/#include<stdio.h>#include<string.h>#include<math.h>int main(){freopen("calfflac.in","r",stdin);freopen("calfflac.ou

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.2 Palindromic Squares(进制转化)

考察进制转化 注意一些细节就可以了 直接上代码: /*ID: who jayLANG: C++TASK: palsquare*/#include<stdio.h>int x[20],xlen,y[20],ylen,B;void change(int n){int m;m=n;xlen=0;while(m){x[++xlen]=m%B;m/=B;}m=n*n;ylen=0;whi