poj 1141 Brackets Sequence(区间dp)

题目链接

Brackets Sequence
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 26254 Accepted: 7394 Special Judge

Description

Let us define a regular brackets sequence in the following way:

1. Empty sequence is a regular sequence.
2. If S is a regular sequence, then (S) and [S] are both regular sequences.
3. If A and B are regular sequences, then AB is a regular sequence.

For example, all of the following sequences of characters are regular brackets sequences:

(), [], (()), ([]), ()[], ()[()]

And all of the following character sequences are not:

(, [, ), )(, ([)], ([(]

Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.

Input

The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.

Output

Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.

Sample Input

([(]

Sample Output

()[()]

Source


题意:给一个只包含括号的串,问最少添加多少个串让该括号串合法,输出合法的括号串。

题解:我们考虑让括号串的第一括号匹配,那么,这个括号要么与已有的括号匹配,要么在某个位置添加一个与它匹配的括号。

我们可以用dp[l][r]表示让区间[l,r] 的括号串合法最少要添加多少个括号,转移就是:

1,如果第一个括号为')' 或 ']' ,显然只能在前面添加一个’(‘ 或']' 。

dp[l][r]=dp[l+1][r]+1;

2,如果第一个括号与第i个括号匹配,那么区间[l+1,i-1]和区间[i+1,r]的括号没有相互影响

dp[l][r]=min(dp[l+1][i-1]+dp[i+1][r])

3,如果在位置i和i+1之间添加一个括号与第一个括号匹配,那么区间[l+1,i]和区间[i+1,r] 之间没有影响

dp[l][r]=min(dp[l+1][i]+dp[i+1][r]+1)

在dp转移的过程中记录路径,最后输出方案即可。

代码如下:(注意由于空字符串也为合法串,所以输入的字符串有可能为空)

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<math.h>
#define nn 110
#define inff 0x7fffffff
#define eps 1e-8
typedef long long LL;
const LL inf64=LL(inff)*inff;
using namespace std;
int n;
char s[nn];
int dp[nn][nn];
int lj[nn][nn];
int dfs(int l,int r)
{
    if(dp[l][r]!=-1)
        return dp[l][r];
    if(l>r)
        return 0;
    dp[l][r]=inff;
    if(s[l]==')')
    {
        dp[l][r]=dfs(l+1,r)+1;
        lj[l][r]=0;
        return dp[l][r];
    }
    else if(s[l]==']')
    {
        dp[l][r]=dfs(l+1,r)+1;
        lj[l][r]=0;
        return dp[l][r];
    }
    int i;
    for(i=2*l+2;i<=2*r+2;i++)
    {
        if(i%2)
        {
            if((s[l]=='('&&s[i/2]==')')||(s[l]=='['&&s[i/2]==']'))
            {
                if(dfs(l+1,i/2-1)+dfs(i/2+1,r)<dp[l][r])
                {
                    dp[l][r]=dfs(l+1,i/2-1)+dfs(i/2+1,r);
                    lj[l][r]=i;
                }
            }
        }
        else
        {
            if((dfs(l+1,i/2-1)+dfs(i/2,r)+1)<dp[l][r])
            {
                dp[l][r]=dfs(l+1,i/2-1)+dfs(i/2,r)+1;
                lj[l][r]=i;
            }
        }
    }
    return dp[l][r];
}
void go(int l,int r)
{
    string re="";
    if(l>r)
        return ;
    if(lj[l][r]==0)
    {
        if(s[l]==')')
            printf("()");
        else
            printf("[]");
        go(l+1,r);
        return ;
    }
    if(lj[l][r]%2)
    {
        if(s[l]=='(')
        {
            printf("(");
            go(l+1,lj[l][r]/2-1);
            printf(")");
            go(lj[l][r]/2+1,r);
        }
        else
        {
            putchar('[');
            go(l+1,lj[l][r]/2-1);
            putchar(']');
            go(lj[l][r]/2+1,r);
        }
    }
    else
    {
        if(s[l]=='(')
        {
            putchar('(');
            go(l+1,lj[l][r]/2-1);
            putchar(')');
            go(lj[l][r]/2,r);
        }
        else
        {
            putchar('[');
            go(l+1,lj[l][r]/2-1);
            putchar(']');
            go(lj[l][r]/2,r);
        }
    }
}
int main()
{
    int i;
    while(gets(s))
    {
        int len=strlen(s);
        memset(dp,-1,sizeof(dp));
        dfs(0,len-1);
        //cout<<dfs(0,len-1)<<endl;
        go(0,len-1);
        puts("");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值