UVA题目10157 - Expressions(DP+高精度)

Let X be the set of correctly built parenthesis expressions. The elements of X are strings consisting only
of the characters ‘(’ and ‘)’. The set X is defined as follows:
• an empty string belongs to X
• if A belongs to X, then (A) belongs to X
• if both A and B belong to X, then the concatenation AB belongs to X.
For example, the following strings are correctly built parenthesis expressions (and therefore belong
to the set X):
()(())()
(()(()))
The expressions below are not correctly built parenthesis expressions (and are thus not in X):
(()))(()
())(()
Let E be a correctly built parenthesis expression (therefore E is a string belonging to X).
The length of E is the number of single parenthesis (characters) in E.
The depth D(E) of E is defined as follows:
D(E) =



0 if E is empty
D(A) + 1 if E = (A), and A is in X
max(D(A), D(B)) if E = AB, and A, B are in X
For example, the length of “()(())()” is 8, and its depth is 2. What is the number of correctly
built parenthesis expressions of length n and depth d, for given positive integers n and d?
Write a program which
• reads two integers n and d
• computes the number of correctly built parenthesis expressions of length n and depth d;
Input
Input consists of lines of pairs of two integers - n and d, at most one pair on line, 2 ≤ n ≤ 300,
1 ≤ d ≤ 150.
The number of lines in the input file is at most 20, the input may contain empty lines, which you
don’t need to consider.
Output
For every pair of integers in the input write single integer on one line - the number of correctly built
parenthesis expressions of length n and depth d.
Note: There are exactly three correctly built parenthesis expressions of length 6 and depth 2:
(())()
()(())
(()())
Sample Input
6 2
300 150
Sample Output
3

1

题目大意:n个括号,深度为d的种类有多种,

分成两部分,dp[i][j]表示i对,深度最多为j的有多少种,把括号分为两部分,一部分深度不超过j,一部分不超过j-1

转移方程dp[i][j]=dp[k][j-1]*dp[i-k-1][j]+dp[i][j];

深度的话就减一下就好了dp[n/2][m]-dp[n/2][m-1];

ac代码

16453524 10157 Expressions Accepted C++ 4.216 2015-11-18 07:47:56
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int M=155;
const int N=105;
struct bign {
    int len, sex;
    int s[N];

    bign() {
        this -> len = 1;
        this -> sex = 0;
        memset(s, 0, sizeof(s));
    }

    bign operator = (const char *number) {
        int begin = 0;
        len = 0;
        sex = 1;
        if (number[begin] == '-') {
            sex = -1;
            begin++;
        }
        else if (number[begin] == '+')
            begin++;

        for (int j = begin; number[j]; j++)
            s[len++] = number[j] - '0';
    }

    bign operator = (int number) {
        char string[N];
        sprintf(string, "%d", number);
        *this = string;
        return *this;
    }

    bign (int number) {*this = number;}
    bign (const char* number) {*this = number;}

    bign change(bign cur) {
        bign now;
        now = cur;
        for (int i = 0; i < cur.len; i++)
            now.s[i] = cur.s[cur.len - i - 1];
        return now;
    }

    void delZore() {    // 删除前导0.
        bign now = change(*this);
        while (now.s[now.len - 1] == 0 && now.len > 1) {
            now.len--;
        }
        *this = change(now);
    }

    void put() {    // 输出数值。
        delZore();
        if (sex < 0 && (len != 1 || s[0] != 0))
            cout << "-";
        for (int i = 0; i < len; i++)
            cout << s[i];
    }

    bign operator + (const bign &cur){
        bign sum, a, b;
        sum.len = 0;
        a = a.change(*this);
        b = b.change(cur);

        for (int i = 0, g = 0; g || i < a.len || i < b.len; i++){
            int x = g;
            if (i < a.len) x += a.s[i];
            if (i < b.len) x += b.s[i];
            sum.s[sum.len++] = x % 10;
            g = x / 10;
        }
        return sum.change(sum);
    }

    bign operator * (const bign &cur){
        bign sum, a, b;
        sum.len = 0;
        a = a.change(*this);
        b = b.change(cur);

        for (int i = 0; i < a.len; i++){
            int g = 0;

            for (int j = 0; j < b.len; j++){
                int x = a.s[i] * b.s[j] + g + sum.s[i + j];
                sum.s[i + j] = x % 10;
                g = x / 10;
            }
            sum.len = i + b.len;

            while (g){
                sum.s[sum.len++] = g % 10;
                g = g / 10;
            }
        }
        return sum.change(sum);
    }

    bign operator - (const bign &cur) {
        bign sum, a, b;
        sum.len = len;
        a = a.change(*this);
        b = b.change(cur);

        for (int i = 0; i < b.len; i++) {
            sum.s[i] = a.s[i] - b.s[i] + sum.s[i];
            if (sum.s[i] < 0) {
                sum.s[i] += 10;
                sum.s[i + 1]--;
            }
        }
        for (int i = b.len; i < a.len; i++) {
            sum.s[i] += a.s[i];
            if (sum.s[i] < 0) {
                sum.s[i] += 10;
                sum.s[i + 1]--;
            }
        }
        return sum.change(sum);
    }
};
bign dp[M][M];
void DP()
{
    int i,j,k;
    for(i=0;i<=150;i++)
        dp[0][i]=1;
    for(i=1;i<=150;i++)
    {
        for(j=1;j<=150;j++)
        {
            for(k=0;k<i;k++)
            {
                dp[i][j]=dp[k][j-1]*dp[i-k-1][j]+dp[i][j];
            }
        }
    }
}
int main()
{
    int n,m;
    DP();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        bign sum=dp[n/2][m]-dp[n/2][m-1];
        sum.put();
        printf("\n");
    }
}


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yu_ch_sh/article/details/49908255
个人分类: 大数 动态规划
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭