PAT TOP 1007 Red-black Tree (35)

问题描述:

1007 Red-black Tree (35 分)

There is a kind of binary tree named red-black tree in the data structure. It has the following 5 properties:

  • (1) Every node is either red or black.
  • (2) The root is black.
  • (3) All the leaves are NULL nodes and are colored black.
  • (4) Each red node must have 2 black descends (may be NULL).
  • (5) All simple paths from any node x to a descendant leaf have the same number of black nodes.

We call a non-NULL node an internal node. From property (5) we can define the black-height of a red-black tree as the number of nodes on the simple path from the root (excluding the root itself) to any NULL leaf (including the NULL leaf). And we can derive that a red-black tree with black height H has at least 2​H​​−1 internal nodes.

Here comes the question: given a positive N, how many distinct red-black trees are there that consist of exactly N internal nodes?

Input Specification:

Each input file contains one test case which gives a positive integer N (≤500).

Output Specification:

For each case, print in a line the number of distinct red-black tees with N internal nodes. Since the answer may be very large, output the remainder of it divided by 1000000007 please.

Sample Input:

5

Sample Output:

8

 

 这一题也是要用动态规划的一题。注意到红黑树两棵子树的黑色高度是相同的,可以分别设置红根树vr[i][j]和黑根树vb[i][j],其中i表示树的黑色高度(从1开始),j表示树中的结点数量(从1开始)。

对于红根树来说,它的两棵子树都是黑根树,并且它的黑色高度和子树相同:

vr[i][j+k+1]=vb[i][j]*vb[i][k]

对于黑根树来说,它的两棵子的根颜色可以任意,只要保证它的黑色高度是子树的黑色高度加一:

vb[i+1][j+k+1]=(vr[i][j]+vb[i][j])*(vr[i][k]+vb[i][k])

初始条件是vb[1][1]=1(对应于单个节点黑根树);vb[1][2]=2(对应于黑根树有一个左/右红色孩子);vb[1][3]=1(对应于黑根树有两个红色孩子);

最后...注意正确地取模数,最后一个点是关于n较小的情况,也应该考虑到。。。

 

AC代码:

#include<bits/stdc++.h>
using namespace std;
vector<long long> vr;
vector<long long> vb;
#define mod 1000000007
int main()
{
//  	freopen("data.txt","r",stdin);
  	int n;
  	scanf("%d",&n);
  	int m=min(n,10);
  	vr.resize(n*m,0);
   	vb.resize(n*m,0);
   	if(n)
   	{
		vb[0]=1;
		vb[1]=2;
		vb[2]=1;
	}
  	for(int i=1;i<m;i++)
  	{
		for(int j=2;j<n;j++)
		{
			for(int k=0;k<j-1;k++)
			{
				long long s1=(vb[(i-1)*n+k]+vr[(i-1)*n+k])%mod;
				long long s2=(vb[(i-1)*n+j-k-2]+vr[(i-1)*n+j-k-2])%mod;
				vb[i*n+j]+=(s1*s2)%mod;
				vb[i*n+j]%=mod;
				vr[(i-1)*n+j]+=((vb[(i-1)*n+k]%mod)*(vb[(i-1)*n+j-2-k]%mod));
				vr[(i-1)*n+j]%=mod;
			}
		}
	}
	long long s=0;
	for(int i=0;i<m;i++)
	(s+=vb[i*n+n-1])%=mod;
	printf("%lld",s);
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值