[USACO2.3]奶牛家谱 Cow Pedigrees

[USACO2.3]奶牛家谱 Cow Pedigrees

题目

[USACO2.3]奶牛家谱 Cow Pedigrees_第1张图片题目链接(luogu)

思路

dp,开始随便写了个dfs结果得了33分。看标签发现是dp,然后发现dp确实可行。(一下方法应该不是最优的)
d p [ i ] [ k ] 代 表 节 点 数 目 为 i 深 度 为 k 的 结 构 数 , 转 移 方 程 如 下 : dp[i][k]代表节点数目为i深度为k的结构数,转移方程如下: dp[i][k]ik
d p [ i ] [ k ] = ∑ m = 1 k − 1 ∑ j = 1 i − 2 f ∗ d p [ j ] [ k − 1 ] ∗ d p [ i − 1 − j ] [ m ] dp[i][k] =\sum_{m=1}^{k-1}\sum _{j=1}^{i-2}f*dp[j][k-1]*dp[i-1-j][m] dp[i][k]=m=1k1j=1i2fdp[j][k1]dp[i1j][m]
其中 j ∈ [ 1 , i − 2 ] , m ∈ [ 1 , k − 1 ] , f = 1 + ( k − 1 = = m   ?   0 : 1 ) j \in[1,i-2],m\in[1,k-1],f=1+(k-1==m\ ?\ 0:1) j[1,i2],m[1,k1],f=1+(k1==m ? 0:1)
解释如下:对于一个具有i个节点的高度为k的树,我们考虑其构成,可能是有一个具有j个节点的深度为的k-1左子树和具有i-1-j个节点的高度为m(m<=k-1)的右子树构成,当然也可以把这两个子树的位置对调。所以当两边子树高度不等的时候直接乘以2,就是所有方案。

#include 
using namespace std;
const int mod = 9901;
#define rep(i, a, b) for (int i = a; i < b; i++)
#define rep_(i, a, b) for (int i = a; i <= b; i++)
int n, k;
int dp[210][110];
int main() {
	cin >> n >> k;
	dp[1][1] = 1;
	rep_(i, 2, n) {
		rep_(h, 1, (i-1)/2+1) {
			rep_(j, 1, i-2) {
				rep_(m, 1, h-1) {
            		int f = 1;
            		if (m != h-1) f = 2;
				 	dp[i][h] = (dp[i][h] + f * dp[j][h-1] * dp[i-1-j][m]) % mod;
				}
			}
		}
	}
	cout << dp[n][k] << endl;
	return 0;
}

你可能感兴趣的:(USACO)