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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章