Brackets-学习DP2

原创 2012年03月27日 23:31:51

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,明天再把它切一遍

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Codeforces Round #343 (Div. 2) C. Famil Door and Brackets(dp)

题意: 给定M≤N≤105,M为原始括号序列s的长度,现要求寻找p,q括号序列给定M\le N \le 10^5, M为原始括号序列s的长度, 现要求寻找p, q括号序列 要求|p+s+q|...
  • lwt36
  • lwt36
  • 2016-02-26 23:09
  • 176

Codeforces Round #343 (Div. 2) C. Famil Door and Brackets(简单dp)

题目链接:点这里!!!! 题意: 给你一长度为m仅包含'('和')'的字符串s,叫你组成一个长度为n的字符串。 使得满足下列两个条件: 1、字符串中'('和')'的数量是相等的。 2...

Codeforces Round #106(Div. 2) 149D. Coloring Brackets 区间DP 记忆化搜索

D. Coloring Brackets time limit per test 2 seconds memory limit per test 256 megabytes ...

Codeforces Round #343 (Div. 2) (C. Famil Door and Brackets(DP))

题目链接:点击打开链接 题意:给你一个长度为m的只含()的括号串s, 要求在s两端在加两个串p和q, 使得总长度为n,并且平衡, 平衡是指任意前缀串的(都不少于), 并且整个串的(和)一样多。 思...

POJ 1141 Brackets Sequence (区间DP)

 这是一道挺好的区间DP题,类似往一个序列里插入东西的问题都可以往从中间分开考虑两块这个方向去想。 dp[i][j]表示i到j这一段最少需要插入括号的数量,显然这个数等于min(dp[i][k...

100道动态规划——3 UVA 2451 Brackets sequence 重构解 DP

好吧,这道题的难点在于重构解,我发现我写的题目基本上只要输出一个答案,要重构解得很少呀。。重构解写了我大约1H左右。。。还是不熟练呀。。                  至于求得解得个数的话,区间...

POJ1141 ZOJ1463 Brackets Sequence【区间dp】

题意十分简单,然而卡了我一上午,也怪自己状态不好,学成这样还想着玩?! 给定字符串,问最终匹配成的字符串【】() 开始还以为是像poj2955Brackets【区间dp 括号匹配】 这样的,结果是难...

codeferces 149D Coloring Brackets 区间dp

http://codeforces.com/problemset/problem/149/D 题目大致意思是给你一串字符串,只有小括号,并且已经符合括号匹配规则,现在要给这些括号涂色,给出一些涂...

UVa 1626:Brackets Sequence(DP)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=847&page=show_pr...

poj 2955 Brackets(区间dp)

Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3376   Accep...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)