南阳理工学院动态规划专题括号问题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
来源
上传者