nyoj 15 括号匹配(二) (经典dp)

时间:2023-03-08 20:47:13

题目链接

描述

给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。

如:

[]是匹配的

([])[]是匹配的

((]是不匹配的

([)]是不匹配的

输入

第一行输入一个正整数N,表示测试数据组数(N<=10)

每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100

输出

对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行

样例输入

4

[]

([])[]

((]

([)]

样例输出

0

0

3

2

分析:

首先,这个问题具体是很经典的区间动态规划问题,那么,我们可以使用一个二维数组dp[i][j] 表示字符串s的第i..j字符匹配后需要添加的最少括号数,下面是具体的表示:

当i= j的时候,只有一个字符,那么,只要匹配一个字符就行了,所以,dp[i][i] = 1

如果,当i < j的时候,s[i] = s[j] 那么,dp[i][j] = min(dp[i][j],dp[i+1][j-1]),其中,假设i <= k < j 状态转移方程为 dp[i][j] = min(dp[i][j],d[i][k] + dp[k+1][j])

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char ch[109];
int dp[109][109];///dp[i][j]表示的是从第i个字符到第j个字符,想要匹配需要添加的字符数
bool cmp(char a,char b)///看字符a和字符b是否匹配
{
if((a=='('&&b==')')||(a=='['&&b==']'))
return true;
return false;
}
void solve(int len)
{
memset(dp,0,sizeof(dp));
for(int i=0; i<len; i++) ///自己到自己如果想要匹配的话,肯定都得添加一个
dp[i][i]=1;
for(int w=1; w<len; w++)///控制的是字符匹配的间距
{
for(int i=0; i<len-w; i++)///开始的字符
{
int j=i+w;///表示的是结束字符的下标
dp[i][j]=0x3f3f3f3f;
if(cmp(ch[i],ch[j]))///如果他们本身就是匹配的话
dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
for(int k=i; k<j; k++)///将区间分成两段来松弛
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
printf("%d\n",dp[0][len-1]);
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%s",ch);
int k=strlen(ch);
solve(k);
}
}