括号匹配(二)NYOJ(区间dp)

括号匹配(二)
时间限制:1000 ms | 内存限制:65535 KB
难度:6
描述
给你一个字符串,里面只包含”(“,”)”,”[“,”]”四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
输入
第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
输出
对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
样例输入
4
[]
([])[]
((]
([)]
样例输出
0
0
3
2
来源
《算法艺术与信息学竞赛》
上传者
张云聪

分析:
这是一题比较典型的区间dp题。首先我们需要先定义状态:dp[i][j]:表示在区间[i,j]需要添加的最少括号个数。根据不同结构,可以分为以下 4 种不同情况来处理:
1)S 形如(S′)或[S′]:
只需把 S′变规则即可,则 f[i,j]= f[i+1,j-1]。
2)S 形如(S′或[S′: 先把 S′化为规则的,右边加“)”或“]”即可,则 f[i,j]= f[i+1,j]+1。
3)S 形如 S′)或 S′]: 先把 S′化为规则的,左边加“(”或“[”即可,则 f[i,j]= f[i,j-1]+1
4)把长度大于 1 的序列 SiSi+1..Sj-1Sj分为两部分: Si..Sk,Sk+1.. Sj,分别化为规则序列,则 f[i,j]=f[i,k]+f[k+1,j] ;i<=k<=j-1; 上述 4 种情况取最小值即可。

特殊数据
()() 0
(我就是卡上面那个数据卡了很久)

Accepted code:



#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=205;
int dp[maxn][maxn];
char s[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        int n=(int)strlen(s);
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++) dp[i][i]=1;

        for(int i=n;i>=0;i--)
        {
            for(int j=i;j<n;j++)
            {
                int temp=0x3f3f3f3f;
                if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
                {
                    temp=dp[i+1][j-1];
                }

                for(int k=i;k<j;k++)
                {
                    temp=min(temp,dp[i][k]+dp[k+1][j]);
                }
                int v1=0x3f3f3f3f,v2=0x3f3f3f3f;
                if(s[j]==')'||s[j]==']')
                    v1=dp[i][j-1]+1;
                if(s[i]=='('||s[i]=='[')
                    v2=dp[i+1][j]+1;
                dp[i][j]=min(v1,min(v2,temp));

            }
        }
        printf("%d\n",dp[0][n-1]);
    }
}

猜你喜欢

转载自blog.csdn.net/QingyingLiu/article/details/80672154
今日推荐