关闭

Brackets-学习DP2

标签: characterinputceachtagsfile
217人阅读 评论(0) 收藏 举报
分类:

Brackets

My Tags   (Edit)
  Source : Stanford ACM Programming Contest 2004
  Time limit : 1 sec   Memory limit : 32 M

Submitted : 172, Accepted : 101

5.1 Description

We give the following inductive definition of a “regular brackets” sequence:

• the empty sequence is a regular brackets sequence,

• if s is a regularbrackets sequence,then(s)and[s]are regular brackets sequences, and

• if a and b are regular brackets sequences, then ab is a regular brackets sequence.

• no other sequence is a regular brackets sequence

For instance, all of the following character sequences are regular brackets sequences:

(), [], (()), ()[], ()[()]

while the following character sequences are not:

(, ], )(, ([)], ([(]

Given a brackets sequence of characters a1a2 ...an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1,i2,...,im where 1 ≤ i1 < i2 < ...< im ≤ n, ai1ai2 ...aim is a regular brackets sequence.

5.2 Example

Given the initial sequence ([([]])], the longest regular brackets subsequence is [([])].

5.3 Input

The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters (, ), [, and ]; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed. For example:

((()))
()()()
([]])
)[)(
([][][)
end

5.4 Output

For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line. For example:

6
6
4
0
6

/*较高效的非递归的写法*/

/*用递归还有一个0.57秒的写法,感觉还是很不错的思想,

 * 虽然递归慢很多,不过记忆的方法就加速使其没有超时*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAX = 110;
char c[MAX];
int dp[MAX][MAX];

int main() {
    while (scanf(" %s", &c) && c[0] != 'e') {
        int size = strlen(c);
        memset(dp, 0, sizeof (dp));

        for (int step = 1; step < size; step++) {
            for (int start = 0; start + step < size; start++) {
                int end = start + step;
                if ((c[start] == '[' && c[end] == ']') || (c[start] == '(' && c[end] == ')')) {
                    dp[start][end] = dp[start + 1][end - 1] + 1;
                }
                for (int mid = start; mid < end; mid++) {/*注意:mid从start开始,注意宁多勿少,因为可能会少考虑一些情况*/
                    dp[start][end] = max(dp[start][end], dp[start][mid] + dp[mid + 1][end]);
                }
            }
        }
        printf("%d\n", 2 * dp[0][size - 1]);
    }
    return 0;

}


/*很有成就感的递归写法,忽然间使用记忆的方法进行减枝同样可以AC*/

#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAX = 110;
int a[MAX];
int b[MAX];
bool color_a[MAX];
bool color_b[MAX];
int size_a;
int size_b;
char c[MAX];

void init(int size_c) {
    memset(color_a, 0, sizeof (color_a));
    memset(color_b, 0, sizeof (color_b));
    size_a = 0;
    size_b = 0;
    for (int i = 0; i < size_c; i++) {
        if (c[i] == ')') {
            a[size_a++] = i;
        } else if (c[i] == ']') {
            b[size_b++] = i;
        }
    }
}
int d[MAX][MAX];

int DFS(int start, int end) {
    if (start >= end) return 0;
    if (d[start][end] > 0) return d[start][end] - 1;
    int min_size = 0;
    for (int i = start; i <= end; i++) {
        if (c[i] == '(') {
            for (int j = 0; j < size_a && a[j] <= end; j++) {
                if (a[j] > i && color_a[j] == false) {
                    color_a[j] = true;
                    min_size = max(min_size, 2 + DFS(start, i - 1) + DFS(i + 1, a[j] - 1) + DFS(a[j] + 1, end));
                    color_a[j] = false; //现场还原
                }
            }
        } else if (c[i] == '[') {
            for (int j = 0; j < size_b && b[j] <= end; j++) {
                if (b[j] > i && color_b[j] == false) {
                    color_b[j] = true;
                    min_size = max(min_size, 2 + DFS(start, i - 1) + DFS(i + 1, b[j] - 1) + DFS(b[j] + 1, end));
                    color_b[j] = false; //现场还原
                }
            }
        }
    }
    d[start][end] = min_size + 1; 
    return min_size;
}

int main() {
    while (scanf(" %s", &c) && c[0] != 'e') {
        int size_c = strlen(c);
        init(size_c);

        memset(d, 0, sizeof (d));
        printf("%d\n", DFS(0, size_c - 1));
    }
    return 0;
}

他还有一个姊妹题,不同就是要你打出一组情况,这个需要记忆,也是不错的,递归输出的典型案例:

Brackets Sequence,明天再把它切一遍

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:81679次
    • 积分:1430
    • 等级:
    • 排名:千里之外
    • 原创:62篇
    • 转载:2篇
    • 译文:0篇
    • 评论:17条
    最新评论