南阳理工学院动态规划专题括号问题2总结
这道题目初看起来很简单,但是我从看题到思考,到做题ac足足花了一个晚上加一个下午的时间,我也有到网上找代码的习惯,但是都是递归,特别蛋疼,我想用正统的动归去做,于是就开始了不一样的艰难探索之旅。
分析过程:
使用char str[1001]这个字符数组保存最初输入的括号序列,使用dp[1001][1001]这个数组保存中间结果,dp[i][j]的意思是从下标为i的字符到下标为j的字符的子问题最少要加多少个括号才能规范化。首先dp数组初始化为零,显然dp[i][i]=1;至于dp[i][i+1],当str[i][i+1]配对的时候=0,当str[i][i+1]不配对的时候=2;到了这一步初始化工作结束。
如果str[i]和str[j]配对则分为两种情况:
1. i->(…)(…)<-j,则dp[i][j]=min{dp[i][k]+dp[k+1][j]};
2. i->(..(..)..)<-j,则dp[i][j]=dp[i+1][j-1],因为之前dp[i+1][j-1]已经计算过,因此直接使用即可。
如果str[i]和str[j]不配对分为四种情况:
1. 在str[i+1]到str[j]的字串当中有与str[i]配对的括号,其对应的下标序列为k1,k2,k3,…
则dp[i][j]=min{dp[i][k1]+dp[k1+1][j], dp[i][k2]+dp[k2+1][j],dp[i][k3]+dp[k3+1][j],…};
2. 当不存在与str[i]相匹配的括号时直接使用dp[i][j]=dp[i+1][j]+1;
3. 在str[i]到str[j-1]的字串当中有与str[j]配对的括号,其对应的下标序列为k1,k2,k3,…
则dp[i][j]=min{dp[i][k1-1]+dp[k1][j], dp[i][k2-1]+dp[k2][j],dp[i][k3-1]+dp[k3][j],…};
4. 不存在与str[i]相匹配的括号时直接使用dp[i][j]=dp[i][j-1]+1;
计算完成后dp[0][strlen(str)-1]即是计算结果。
Ac代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#define INF 100000000
using namespace std;
char str[101];
int dp[101][101];
bool match(char ch1,char ch2)
{
if(ch1=='('&&ch2==')')return true;
if(ch1=='['&&ch2==']')return true;
return false;
}
int main()
{
int cas;
cin>>cas;
while(cas--)
{
int top=-1;
memset(str,0,sizeof(str));
cin>>str;
int l1=strlen(str);
if(l1==0)
{
cout<<"0"<<endl;
continue;
}
for(int i=0;i<l1;i++)dp[i][i]=1;
for(int i=0;i<l1-1;i++)
{
if(match(str[i],str[i+1]))
{
dp[i][i+1]=0;
}
else{dp[i][i+1]=2;}
}
for(int k=2;k<l1;k++)
{
for(int i=0;i+k<l1;i++)
{
int j=i+k;
if(match(str[i],str[j]))
{
int min1=INF;
for(int kk=i+1;kk<j;kk++)
{
intt=dp[i][kk]+dp[kk+1][j];
if(min1>t)
min1=t;
}
int min2=dp[i+1][j-1];
dp[i][j]=min(min1,min2);
}
else
{
int min1=INF;
for(int kk=i+1;kk<j;kk++)
{
if(match(str[i],str[kk]))//检查左端
{
intt=dp[i][kk]+dp[kk+1][j];
if(min1>t)
min1=t;
}
}
int min2=dp[i+1][j]+1;
int min3=IN
for(intkk=i+1;kk<j;kk++)//检查右端
{
if(match(str[kk],str[j]))
{
intt=dp[i][kk-1]+dp[kk][j];
if(min3>t)
min1=t;
}
}
int min4=dp[i][j-1]+1;
dp[i][j]=min(min(min1,min2),min(min3,min4));
}
}
}
cout<<dp[0][l1-1]<<endl;
// for(int i=0;i<l1;i++)
// {
// for(int j=0;j<l1;j++)
// {
// cout<<dp[i][j]<<' ';
// }
// cout<<endl;
// }
}
}
括号匹配(二)
时间限制:1000 ms | 内存限制:65535 KB
难度:6
描述
给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
输入
第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
输出
对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
样例输入
4
[]
([])[]
((]
([)]
样例输出
0
0
3
2
来源
上传者