UVa #1626 Brackets sequence (例题9-10)

86 篇文章 0 订阅

动态规划的意味还是挺明显的:如果子结构A、B都ok,则AB也ok。如果Aok,则(A)、[A]也ok。


那么对于一个序列,我们只要扫描他所有的子结构,取子结构中dp值最小的就好了。边界条件是1、单独一个元素,这时因为无法配对,一定要加上另外一半的括号,因此dp值为1;2、一对配好对的括号,dp值为0。


打印解:再次用到了Ideal Path的方法。因为只用打印任意一组解,找到第一个dp值相同的一对子结构就可以递归然后return了。这个return不能忘记,否则会打印出多组解掺杂在一起。


UVa第一百题,再接再厉!


Run Time: 0.985s

#define UVa  "LT9-10.1626.cpp"		//
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

//Global Variables. Reset upon Each Case!
const int maxn = 100 + 10;
int d[maxn][maxn];
char dummy, s[maxn];
/

int match(char a, char b) {
    if( (a == '(' && b == ')') || (a == '[' && b == ']')) return 1;
    return 0;
}

void print_ans(int i, int j) {
    if(i == j) printf("%s", (s[i] == '(' || s[i] == ')')?"()":"[]");
    else {
        for(int k = i; k < j; k ++) {
            if(d[i][j] == d[i][k] + d[k+1][j]){
                print_ans(i, k);
                print_ans(k+1, j);
                return;
            }
        }
        if(d[i][j] == d[i+1][j-1]) {
            if(i == j-1) printf("%c%c", s[i], s[j]);
            else {
                printf("%c", s[i]);
                print_ans(i+1, j-1);
                printf("%c", s[j]);
            }
            return;
        }
    }
}

int main() {
    int kase;
    scanf("%d", &kase);
    gets(s);

    while(kase--) {
        gets(s);
        gets(s);
        int n = strlen(s);
        if(n) {
            for(int len = 0; len < n; len ++) {
                for(int i = 0; i+len < n; i ++) {
                    int j = i + len;
                    if(len == 0) d[i][j] = 1;       //single bracket.
                    else {
                        d[i][j] = d[i][i] + d[i+1][j];
                        for(int k = i + 1; k < j; k ++)
                            d[i][j] = min(d[i][j], d[i][k] + d[k+1][j]);
                        if(match(s[i],s[j])) {
                            if(i == j - 1) d[i][j] = 0;
                            else d[i][j] = min(d[i][j], d[i+1][j-1]);
                        }
                    }
                }
            }
            print_ans(0, n-1);
        }
        printf("\n");
        if(kase) printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值