zoukankan      html  css  js  c++  java
  • poj1095

    题意:给出n,要求输出第n个二叉树,二叉树编号规则如下图所示:

    分析:g[i]表示有i个节点的二叉树,有多少种。f[i][j]表示有i个节点,且左子树有j个节点的树有多少种。

    sumg[i]表示g数组前i个的和。sumf[i][j]表示f[i]数组前j项的和。

    有g[i]=sum(f[i][j]),f[i][j]=g[j]*g[i - 1 - j]。

    对于一个输入的n,我们先通过对sumg进行二分查找以确定节点数量,然后递归求解。

    递归包含两个参数:1、当前子树节点数量tot。2、要求第num个具有这些节点的子树。

    接下来在sumf[tot]中对num进行二分查找,即可确定其左子树节点个数x,从而确定其右子树的节点个数y。

    通过g[y](右子树的变化数)可以判定左子树处于第几个形态。计算公式为(num - sumf[tot][x - 1]) / g[y];

    同样可以确定右子树处于哪一种形态。计算公式为(num - sumf[tot][x - 1]) % g[y];

    #include <iostream>
    using namespace std;
    
    const    long long    maxx = 30;
    
    long long        f[maxx][maxx], g[maxx], sumg[maxx], sumf[maxx][maxx], n;
    
    long long binarysearch(long long *array, long long start, long long end, long long goal)
    {
        long long        l, r, mid;
    
        l = start;
        r = end;
        while (l < r)
        {
            mid = (l + r) / 2;
            if (array[mid] < goal)
                l = mid + 1;
            else
                r = mid;
        }
        return l;
    }
    
    void dfs(long long tot, long long num)
    {
        long long        x = binarysearch(sumf[tot], 0, tot - 1, num), a, b;
    
        if (x > 0)
        {
            a = (num - sumf[tot][x - 1]) / g[tot - x - 1];
            b = (num - sumf[tot][x - 1]) % g[tot - x - 1];
            if (b == 0)
                b = g[tot - x - 1];
            else
                a++;
            printf("(");
            dfs(x, a);
            printf(")");
            num = b;
        }
        printf("X");
        if (tot - 1 - x > 0)
        {
            printf("(");
            dfs(tot - x - 1, num);
            printf(")");
        }
    }
    
    void work()
    {
        long long        num;
    
        num = binarysearch(sumg, 0, maxx, n);
        n -= sumg[num - 1];
        dfs(num, n);
        printf("
    ");
    }
    
    int main()
    {
        long long        i, j;
        
        //freopen("t.txt", "r", stdin);
        f[1][0] = 1;
        g[0] = 1;
        sumg[0] = 0;
        g[1] = sumg[1] = 1;
        for (i = 2; i < maxx; i++)
        {
            g[i] = sumf[i][0] = f[i][0] = g[i - 1];
            for (j = 1; j < i; j++)
            {
                f[i][j] = g[j] * g[i - 1 - j];
                g[i] += f[i][j];
                sumf[i][j] = sumf[i][j - 1] + f[i][j];
            }
            sumg[i] = g[i] + sumg[i - 1];
        }
        while (scanf("%d", &n) != EOF && n != 0)
            work();
        return 0;
    }
    View Code
  • 相关阅读:
    素敵な日本人 2-1
    十年目のバレンタインデー のほか
    水晶の数珠  3
    水晶の数珠  2
    STM32 USB HID BarCodeReader不兼容问题的解决
    水晶の数珠 1
    クリスマスミステリ 2
    クリスマスミステリ 1
    サファイア奇跡 3
    感悟成功
  • 原文地址:https://www.cnblogs.com/rainydays/p/3201479.html
Copyright © 2011-2022 走看看