这道题是黑书上的一个例题,不过没有给出最终输出的串,但是可以通过递归把最后的串输出
首先我们定义d[i][j] 为从i位置到j位置的串匹配所需的最少步数
那么当s[i] = '('&& s[j] =')' 或者s[i] = '['&&s[j] =']'时,显然d[i][j] = minI(d[i][j], d[ i + 1][ j - 1])
然后当s[i]和s[j]不匹配的时候,就要对串进行增加,达到匹配
然后我们还可以将串进行拆分,拆成两部分
for k=i to j-1
d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j])
这样才能保证d[i][j]是最小的。
并且,计算d[i][j]时,前提是知道了d[i + 1][j - 1],d[i][j - 1] d[i + 1][j]
所以必须从j-i最小的开始算,逐渐递增
题目求的是最后的串,所以就要开另一个辅助数组v,
v[i][j]记录了一些信息,
当v[i][j] = -1时表示s[i],s[j]已经匹配
当v[i][j]为非负时,表示串在该位置(v[i][j]的值)处进行过拆分,就要分别递归进入这两个串中
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define INF 1000000000
using namespace std;
char s[205];
int d[105][105];
int v[105][105];
void print(int i, int j)
{
if(i > j) return;
if(i == j)
{
if(s[i] == '(' || s[i] == ')')
printf("()");
else printf("[]");
}
else
{
if(v[i][j] == -1)
{
printf("%c", s[i]);
print(i + 1, j - 1);
printf("%c", s[j]);
}
else
{
print(i, v[i][j]);
print(v[i][j] + 1, j);
}
}
}
int main()
{
while(gets(s) != 0)
{
int n = strlen(s);
memset(d, 0, sizeof(d));
memset(v, 0, sizeof(v));
for(int i = 0; i < n; i++)
d[i][i] = 1;
for(int p = 1; p < n; p++)
{
for(int i = 0; i < n - p; i++)
{
int j = i + p;
d[i][j] = INF;
if((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']'))
{
if(d[i][j] > d[i + 1][j - 1])
{
d[i][j] = d[i + 1][j - 1];
v[i][j] = -1;
}
}
for(int k = i; k < j; k++)
{
if(d[i][j] > d[i][k] + d[k + 1][j])
{
d[i][j] = d[i][k] + d[k + 1][j];
v[i][j] = k;
}
}
}
}
print(0, n - 1);
printf("\n");
}
return 0;
}