这一篇关于DP的经典入门讲解非常好: http://www.cnblogs.com/SDJL/archive/2008/08/22/1274312.html#1976963
参考: http://www.cnblogs.com/void/articles/2332513.html
USACO: 讲解
这是一个DP问题。我们所关心的树的性质是深度和节点数,所以我们可以做这样一张表:table[i][j]表示深度为i、节点数为j的树的个数。根据给定的约束条件,j必须为奇数。你如何构造一棵树呢?当然是由更小的树来构造了。一棵深度为i、节点数为j的树可以由两个子树以及一个根结点构造而成。当i、j已经选定时,我们选择左子树的节点数k。这样我们也就知道了右子树的节点数,即j-k-1。至于深度,至少要有一棵子树的深度为i-1才能使构造出的新树深度为i。有三种可能的情况:左子树深度为i-1 ,右子树深度小于i-1;右子树深度为i-1,左子树深度小于i-1;左右子树深度都为i-1。事实上,当我们在构造一棵深度为i的树时,我们只关心使用的子树深度是否为i-1或更小。因此,我们使用另一个数组smalltrees[i-2][j]记录所有深度小于i-1的树,而不仅仅是深度为i-2的树。知道了上面的这些,我们就可以用以下三种可能的方法来建树了:
table[i][j]+= smalltrees[i-2][k]*table[i-1][j-1-k];//左子树深度小于i-1,右子树深度为i-1
table[i][j]+= table[i-1][k]*smalltrees[i-2][j-1-k];//左子树深度为i-1,右子树深度小于i-1
table[i][j]+= table[i-1][k]*table[i-1][j-1-k];//左右子树深度都为i-1 另外,如果左子树更小,我们可以对它进行两次计数,因为可以通过交换左右子树来得到不同的树。总运行时间为O(K*N^2),且有不错的常数因子。(官方标程见源码-c部分)
首先明确一下题目的意思:用N个点组成一棵深度为K的二叉树,求一共有几种方法?设dp[i,j]表示用i个点组成深度最多为j的二叉树的方法数,则:
dp[i,j]=∑(dp[k,j-1]×dp[i-1-k,j-1])(k∈{1..i-2})
边界条件:dp[1,i]=1
我们要求的是深度恰好为K的方法数S,易知S=dp[n,k]-dp[n,k-1]。但需要注意的是,如果每次都取模,最后可能会有dp[n,k]<dp[n,k-1],所以可以用S=(dp[n,k]-dp[n,k-1]+v) mod v。
我的代码:
/*
ID: wangxin12
PROG: nocows
LANG: C++
*/
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
#define MOD 9901
int N, K; // N < 200, K < 100
int ans = 0;
int dp[200][100];
int main() {
ifstream fin("nocows.in");
ofstream fout("nocows.out");
int i,j,k;
//init
fin>>N>>K;
//dp[1][1] = 1;
for(i = 0; i < 100; i++)
dp[1][i] = 1;
// first level
for(i = 1; i <= N; i += 2)
for(j = 2;j <= K; j++) {
for(k = 1; k <= i - 2; k++) {
dp[i][j] = (dp[i][j] + dp[k][j - 1] * dp[i - 1 - k][j - 1]) % MOD;
}
}
ans = (dp[N][K] - dp[N][K - 1] > 0) ? dp[N][K] - dp[N][K - 1] : (dp[N][K] - dp[N][K - 1] + MOD) % MOD;
fout<<ans<<endl;
fin.close();
fout.close();
return 0;
}-----------------------------------------------------------------------------------------
原题:
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 @ @
/ \ / \
@ @ @ @
本文详细解析了一种使用深度优先搜索方法解决构建特定性质二叉树的问题,重点在于通过动态规划构建深度为K、节点数为N的二叉树,详细解释了表的构建过程和边界条件,并提供了C++实现代码。文章还给出了原题的描述和样例输入输出,帮助读者理解实际应用情境。
2841

被折叠的 条评论
为什么被折叠?



