题意
传送门 POJ 1141
题解
设 S , A , B S,A,B S,A,B 为合法的括号序列,则 ( S ) , [ S ] , A B (S),[S],AB (S),[S],AB 也是合法的括号序列。设输入字符串为 s s s, d p [ i ] [ j ] dp[i][j] dp[i][j] 代表 s s s 的区间 [ i , j ] [i,j] [i,j] 转化为的合法括号序列的所需添加的括号的最小数量,区间状态转移为
d p [ i ] [ j ] = { m a x { d p [ i − 1 ] [ j − 1 ] , m a x { d p [ i ] [ k ] + d p [ k + 1 ] [ j ] } } s [ i ] = s [ j ] m a x { d p [ i ] [ k ] + d p [ k + 1 ] [ j ] } o t h e r w i s e dp[i][j]=\begin{cases} max\{dp[i-1][j-1],max\{dp[i][k]+dp[k+1][j]\}\} & s[i]=s[j]\\ max\{dp[i][k]+dp[k+1][j]\} & otherwise \\ \end{cases} dp[i][j]={max{dp[i−1][j−1],max{dp[i][k]+dp[k+1][j]}}max{dp[i][k]+dp[k+1][j]}s[i]=s[j]otherwise
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 105
char s[maxn];
int dp[maxn][maxn], path[maxn][maxn];
bool match(char c1, char c2)
{
return (c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']');
}
void output(int i, int j)
{
if (i > j) return;
if (i == j)
{
printf((s[i] == '(' || s[i] == ')') ? "()" : "[]");
}
else if (path[i][j] == -1)
{
putchar(s[i]);
output(i + 1, j - 1);
putchar(s[j]);
}
else
{
int k = path[i][j];
output(i, k);
output(k + 1, j);
}
}
int main()
{
scanf("%s", s);
int n = strlen(s);
memset(dp, 0, sizeof(dp));
memset(path, -1, sizeof(path));
for (int i = 0; i < n; i++) dp[i][i] = 1;
for (int l = 1; l < n; l++)
{
for (int i = 0; i < n - l; i++)
{
int j = i + l;
dp[i][j] = match(s[i], s[j]) ? dp[i + 1][j - 1] : inf;
for (int k = i; k < j; k++)
{
int tmp = dp[i][k] + dp[k + 1][j];
if (dp[i][j] > tmp)
{
dp[i][j] = tmp, path[i][j] = k;
}
}
}
}
output(0, n - 1);
putchar('\n');
return 0;
}