uva 1626 - Brackets sequence

//
//  main.cpp
//  uva   1626 - Brackets sequence


/*
 这一题应该是经典的矩阵类似问题。
 显然 需要使用两个变量来表示最终的结果。
 设 dp[i][j]表示第i个位置到第j个位置变成合法形式需要添加的字符数。
 注意题目中的合法形式,1-->(A),2-->[A] , 3-->AB 。三种。
 这里  1.如果形式1或者2.则有  dp[i][j] = min(dp[i][j] , dp[i+1][j-1]) .
      2.如果是形式3.则有  dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k+1][j]) ,其中k>=i ,k < j ;
    同时得注意 在递推时,如论如何都要 进入到情况2.因为即使满足形式1和2,不一定是所需添加的字母最少的情况,
     例如:   ()([])
 还有就是递推的方向问题。
 当i== j 时 ,dp[i][i] = 1 ;
 注意i < j .放到矩阵里就是右上角的矩阵。
 再者就是 递推式。递推式要求要先求出同一行的前面的值,还用同一列下面的值。
 所以地推方向可以为  i从 n --> 0 ;j从0-->n.

 */

#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#define ll long long
using namespace std ;

int d[110][110] ;
char s[110] ;
int match(char c1 , char c2)
{
    
    if ((c1 == '('&&c2 == ')')||(c1 == '[' && c2 == ']' )) {
        return 1 ;
    }
    return 0 ;
}
int  min(int a, int b )
{
    return a > b ? b:a ;
}
void dp(int n)
{
    for (int i = 0; i < n ; i++) {
        d[i+1][i] = 0;
        d[i][i] = 1 ;
    }
    for(int i = n -2 ; i > -1;i--)
    {
        for (int j = i+1; j < n ; j++) {
            d[i][j] = n   ;
            if(match(s[i],s[j])) d[i][j] = min(d[i][j] , d[i+1][j-1]) ;
            for (int k =  i ; k < j ; k++) {
                d[i][j] = min(d[i][j] , d[i][k] + d[k+1][j]) ;
            }
        }
    }
}
void  print(int i , int j )
{
    if (i >j ) {
        return ;
    }
    if (i == j ) {
        if(s[i] == '('||s[i] ==')'){
            printf("()") ;
        }
        else{
            printf("[]") ;
        }
        return ;
    }
    if (match(s[i], s[j]))  {
        if (d[i][j] == d[i+1][j-1]) {
            printf("%c" ,s[i]) ; print(i+1, j-1) ;printf("%c" , s[j]) ;
            return ;
        }
    }
    for (int t = i; t< j ; t++) {
        if (d[i][j] == d[i][t] + d[t+1][j]) {
            print(i, t) ; print(t+1, j) ;
            return ;
        }
    }
}
int main(int argc, const char * argv[]) {
    int T ; scanf("%d" ,&T) ;getchar() ;
    for (int i = 0; i < T; i++) {
//        if (i!=0) {
//            printf("\n") ;
//        }
        getchar() ;
        gets(s) ;
        int len = (int) strlen(s) ;
        dp(len) ;
        print(0, len-1) ;
        printf("\n") ;
        if(i < T-1)
        {
            printf("\n") ;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值