POJ 1141 Brackets Sequencec

题意:给你一串括号序列(只包含小括号和中括号),让你找出长度最小的regular brackets sequence包含此子序列.其中的regular brackets sequence定义如下:
1)空序列是一个regular brackets sequence;
2)如果s是一个regular brackets sequence,那么[s] 也是一个regular brackets sequence,(s)也是一个regular brackets sequence.

3)如果A,B都是regular brackets sequence,那么AB也是一个regular brackets sequence.


分析:DP枚举从小到大的每一个区间,求出每一个区间需要添加的括号的最小数量。dp[i][j]表示在区间[i-j]需要添加括号的最小数量。则初始化为dp[i][i]=1(每个单个的括号都要添加一个与之对应的括号才能形成regular brackets sequence),根据条件2,3可得状态转移方程:dp[i][j]=min(dp[i][k]+dp[k+1][j]),(i<=k<j)。当str[i]==str[j]时,有问题的条件2知:dp[i][j]=d[i+1][j-1]。由转台转移方程知,在初始化时dp[i+1][i]要初始化为0。对于输出,另开一个数组记录状态转移方向,回溯输出即可。


Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <set>
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=105;
int dp[maxn][maxn],tag[maxn][maxn];
char str[maxn];
int len;

void print(int s,int e){
    if(s>e) return ;
    if(s==e){
        if(str[s]=='('||str[s]==')') printf("()");
        else printf("[]");
    }
    else if(tag[s][e]==-1){
        printf("%c",str[s]);
        print(s+1,e-1);
        printf("%c",str[e]);
    }
    else {
        print(s,tag[s][e]);
        print(tag[s][e]+1,e);
    }
}

int main()
{
    while(gets(str)){
        len=strlen(str);
        for(int i=0;i<len;i++){
            dp[i][i]=1;
            dp[i+1][i]=0;
        }
        for(int st=1;st<len;st++){
            for(int i=0;i+st<len;i++){
                int j=i+st;
                int tmp=inf;
                if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']')
                    tmp=dp[i+1][j-1];
                tag[i][j]=-1;
                for(int k=i;k<j;k++){
                    int res=dp[i][k]+dp[k+1][j];
                    if(res<tmp){
                        tmp=res;
                        tag[i][j]=k;
                    }
                }
                dp[i][j]=tmp;
            }
        }
        print(0,len-1); printf("\n");
    }
    return 0;
}


你可能感兴趣的:(POJ 1141 Brackets Sequencec)