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

本文探讨使用动态规划方法解决序列匹配问题,通过扫描所有子结构并选取最小dp值实现最优解。边界条件处理和打印解策略确保了算法的正确性和效率。UVa题目实例展示了该方法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划的意味还是挺明显的:如果子结构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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值