题意
求一个字符串中最少需要补多少括号使得字符串为规则字符串
思路
其实看到了序列或者区间问题,就很容易想到定义d[i][j]为从i~j的解,然后方程就自然而然的出来:d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]),但是这样是对的吗,其实不是,对于()来说,如果用方程接出来就是2,但其实是0,为什么呢,其实在分为两个区间的时候,我们是要默认两个区间互不干扰的,那么就是说本来可以有联系的括号被分到两个区间去了,例如:(][),本来刚好的括号()一定会被分开,因为每个区间都要有元素,所以不可能把最外面的括号分到一个区间里去,但是对于不是最外面的括号,例如:([])],我们可以分为([])和[这样就把括号分到了一个区间里去,所以要对最外面的括号单独讨论,就可以把所有的情况都考虑一遍,不会漏解或误解。
代码
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int d[10000][10000];
void dp(int n,string s) {
for (int i = 0; i < n; i++) {
d[i + 1][i] = 0;
d[i][i] = 1;
}
for (int i = n - 2; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
d[i][j] = n;
if ((s[i] == '('&&s[j] == ')') || (s[i] == '['&&s[j] == ']')) d[i][j] = d[i + 1][j - 1];
for (int k = i; k < j; k++) {
d[i][j] = min(d[i][k] + d[k + 1][j], d[i][j]);
}
}
}
}
void myprint(string s,int i,int j) {
if (i > j)
return;
if (i == j) {
if (s[i] == ')' || s[i] == '(')
cout << "()";
else
cout << "[]";
return;
}
if (((s[i] == '('&&s[j] == ')') || (s[i] == '['&&s[j] == ']')) && d[i][j] == d[i + 1][j - 1]) {
cout << s[i];
myprint(s, i + 1, j - 1);
cout << s[j];
return;
}
for (int k = i; k < j; k++) {
if (d[i][k] + d[k + 1][j] == d[i][j])
{
myprint(s, i, k);
myprint(s, k + 1, j);
return;
}
}
}
int main() {
string s;
cin >> s;
dp(s.length(), s);
cout << d[0][s.length()-1];
system("pause");
}