//
// 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;
}
uva 1626 - Brackets sequence
最新推荐文章于 2020-10-22 21:19:20 发布