URAL 1183

题目大意:给出一个长度为S的括号序列,求一个以此序列为子序列的最小合法序列。合法即:每种括号的每一个括号都有其相应的匹配。

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

数据规模:1<=S<=100。

理论基础:无。

题目分析:

将一个括号序列合法化无非有以下几种情况:

1.最左边括号与最右边括号匹配。合法化中间括号序列即可。

2.最左边序列与最右边括号不匹配。

1>.最左边括号为左括号,在最右边加右括号。合法化其余括号序列。

2>.最左边括号为右括号,在最左边加左括号。合法化其余括号序列。

3>.最右边括号为右括号,在最左边加左括号。合法化其余括号序列。

4>.最右边括号为左括号,在最右边加右括号。合法化其余括号序列。

答案为:合法化最左边至第j个位置的序列与j+1至最右边的序列,然后相加(最左边<=j<=最右边)得到序列中的长度最小的序列。

通过记忆化搜索即可实现。

代码如下:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<ctime>
#include<vector>
using namespace std;
typedef double db;
#define DBG 1
#define maa (1<<31)
#define mii ((1<<31)-1)
#define ast(b) if(DBG && !(b)) { printf("%d!!|\n", __LINE__); while(1) getchar(); }  //调试
#define dout DBG && cout << __LINE__ << ">>| "
#define pr(x) #x"=" << (x) << " | "
#define mk(x) DBG && cout << __LINE__ << "**| "#x << endl
#define pra(arr, a, b)  if(DBG) {\
    dout<<#arr"[] |" <<endl; \
    for(int i=a,i_b=b;i<=i_b;i++) cout<<"["<<i<<"]="<<arr[i]<<" |"<<((i-(a)+1)%8?" ":"\n"); \
    if((b-a+1)%8) puts("");\
}
template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }
template<class T> inline bool updateMax(T& a, T b) { return a<b? a=b, true: false; }
typedef long long LL;
typedef long unsigned int LU;
typedef long long unsigned int LLU;
#define N 120
string dp[N+1][N+1],ch;
string solve(int l,int r)
{
    if(l>r) return string();
    if(dp[l][r].size())return dp[l][r];
    string res;
    if(l==r)
    {
        if(ch[l]=='('||ch[l]==')')res="()";
        else res="[]";
    }
    else
    {
        if(ch[l]=='('&&ch[r]==')'||ch[l]=='['&&ch[r]==']')
        {
            res.push_back(ch[l]);
            res+=solve(l+1,r-1);
            res.push_back(ch[r]);
        }
        if(ch[l]=='('||ch[l]=='[')
        {
            string tr;
            tr.push_back(ch[l]);
            tr+=solve(l+1,r);
            if(ch[l]=='(')tr.push_back(')');
            else tr.push_back(']');
            if(!res.size()||res.size()>tr.size())res=tr;
        }
        else
        {
            string tr;
            tr=solve(l,l);
            tr+=solve(l+1,r);
            if(!res.size()||res.size()>tr.size())res=tr;
        }
        if(ch[r]==')'||ch[r]==']')
        {
            string tr;
            if(ch[r]==')')tr.push_back('(');
            else tr.push_back('[');
            tr+=solve(l,r-1);
            tr.push_back(ch[r]);
            if(res.size()>tr.size())res=tr;
        }
        else
        {
            string tr;
            tr=solve(l,r-1);
            tr+=solve(r,r);
            if(res.size()>tr.size())res=tr;
        }
    }
    for(int i=l;i<r;i++)
    {
        string s1=solve(l,i);
        string s2=solve(i+1,r);
        if(res.size()>s1.size()+s2.size())res=s1+s2;
    }
    return dp[l][r]=res;
}
int main()
{
    while(cin>>ch)
    {
       cout<<solve(0,ch.size()-1)<<endl;
    }
    return 0;
}

没有其中了,题目分析中已经说的很详细。

by:Jsun_moon http://blog.csdn.net/jsun_moon

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值