1007 Red-black Tree (35分)(C++)

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

题目大意:红黑树需要满足:

  • (1) 每个节点为黑色或红色
  • (2) 根节点黑色
  • (3) 叶子节点为黑色且为空NULL
  • (4) 红色节点的孩子节点为黑(可以为空)
  • (5) 从根节点到任意叶子节点的简单路径经过的黑色节点数相同

现在给出一个红黑树非空节点数n,求对应的红黑树有多少种。

解题思路:动态规划

常规红黑树均为黑根,现定义一个红根红黑树。不难发现一个红黑树的左右子树均为红黑树,即:

一个黑根红黑树的左右子树为黑高相同的两个黑根红黑树、两个红根红黑树或者一红一黑

一个红根红黑树的左右子树为黑高相同的两个黑根红黑树

定义dpB[n][h]:非空节点为n,高度为h的黑根红黑树的个数

       dpR[n][h]:非空节点为n,高度为h的红根红黑树的个数

那么有:dpB[i][j] = dpB[i][j] + (dpB[k][j-1]+dpR[k][j])*(dpB[i-1-k][j-1]+dpR[i-1-k][j])   k=0,1...i-1
              dpR[i][j] = dpR[i][j] + (dpB[k][j-1] * dpB[i-1-k][j-1])   k=0,1...i-1

最终我们要求的结果为dpB[n][0] + dpB[n][1] +...+ dpB[n][maxn]

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
const int mod = 1000000007;
int n, low, high;
long long dpB[maxn][maxn]={}, dpR[maxn][maxn]={}, ans = 0;
int main(){
    scanf("%d", &n);
    dpB[1][1] = 1, dpB[2][1] = 2;
    dpR[1][1] = 1;
    for(int i = 3; i <= n; ++ i){
        low = log2(i+1)/2, high = log2(i+1)*2;
        for(int j = low; j <= high; ++ j){
            for(int k = 1; k < i-1; ++ k){
                dpB[i][j] = (dpB[i][j] + (((dpB[k][j-1]+dpR[k][j])*(dpB[i-1-k][j-1]+dpR[i-1-k][j]))%mod))% mod;
                dpR[i][j] = (dpR[i][j] + (dpB[k][j-1] * dpB[i-1-k][j-1]) % mod) % mod;
            }
        }
    }
    for(int i = 0; i < 30; ++ i)
        ans = (ans + dpB[n][i]) % mod;
    printf("%lld", ans);
}

 

发布了465 篇原创文章 · 获赞 91 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章