南阳理工ACM 括号匹配问题,并求出使得括号能够匹配需要新增的最小括号数(括号匹配(二))
描述
给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
- 输入
- 第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100 - 输出
- 对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
- 样例输入
-
4 [] ([])[] ((] ([)]
- 样例输出
-
0 0 3 2
解题思路
如果仅仅是一般的判断括号是否匹配,直接扫描一遍数组,利用一个栈就可以判定YES还是OR。现在需要求解其输出的个数。可以联想到我们求解矩阵连乘问题,求解何种组合使得计算量最小。利用动态规划的方式求解。
利用公式:M[i,j]=M[i,k]+M[k+1,j](k={i,i+1,...j-1})
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //括号匹配问题 求最大子长 M[i,j]=min(M[i,j],M[i,k]+M[k+1,j] 2 class Program 3 { 4 static void Main(string[] args) 5 { 6 string S = "((]"; 7 int[,] M = new int[S.Length, S.Length]; 8 for (int i = 0; i < S.Length; i++) 9 for (int j = 0; j < S.Length; j++) 10 M[i, j] = -1; 11 Console.WriteLine(NeedLength(0, S.Length - 1, S, M)); 12 for (int i = 0; i < S.Length; i++) 13 { 14 Console.WriteLine(); 15 for (int j = 0; j < S.Length; j++) 16 Console.Write(M[i, j] + " "); 17 } 18 Console.Read(); 19 } 20 //判定是否匹配 21 public static bool isMatch(char x, char y) 22 { 23 bool flag = false; 24 if ((x == '(' && y == ')') || (x == '[' && y == ']')) 25 flag = true; 26 return flag; 27 } 28 /// <summary> 29 /// 求解需要的最少括号数 30 /// </summary> 31 /// <param name="i">从I开始</param> 32 /// <param name="j">到j结束</param> 33 /// <param name="S">匹配数组</param> 34 /// <param name="M">保存i---j需要次数的数组</param> 35 /// <returns></returns> 36 public static int NeedLength(int i, int j, string S, int[,] M) 37 { 38 int ans = 10000; 39 if (M[i, j] != -1) 40 return M[i, j]; 41 if (i == j) 42 { 43 return 1; 44 } 45 if (i > j) 46 return 0; 47 if (isMatch(S[i], S[j]))//如果匹配,则直接i往后移,j往前移 48 { 49 ans = Math.Min(ans, NeedLength(i + 1, j - 1, S, M)); 50 } 51 for (int k = i ; k < j; k++)//求解哪个分解之后,使得结果最小化 52 { 53 ans = Math.Min(ans, NeedLength(i, k, S, M) + NeedLength(k + 1, j, S, M)); 54 } 55 M[i, j] = ans; 56 return M[i, j]; 57 } 58 }