题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=98&page=show_problem&problem=452
用dp[i][j] 记录一段序列,starts from index i, ends with index j,需要添加的char的个数。对于一段序列i~j,如果i, j 配对的话,那么dp[i][j]=dp[i+1][j-1].如果i, j不配对的话,那就需要对序列进行分割,dp[i][j]=dp[i][k]+dp[k+1][j],对k进行for loop找到最佳的k。但是当i, j配对时,并不代表dp[i+1][j-1]是最佳的结果,仍旧需要寻找最佳的k。代码如下:
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
#include <vector>
#include <functional>
#include <cmath>
#include <set>
#define SCF(a) scanf("%d", &a)
#define IN(a) cin>>a
#define FOR(i, a, b) for(int i=a;i<b;i++)
#define Infinity 9999999
typedef long long Int;
using namespace std; int path[][];
char brackets[];
void sprint(int s, int e)
{
if (s > e)
return;
if (s == e)
{
if (brackets[s] == '(' || brackets[s] == ')')
printf("()");
else
printf("[]");
}
else
{
if (path[s][e] == -)
{
printf("%c", brackets[s]);
sprint(s + , e - );
printf("%c", brackets[e]);
}
else
{
sprint(s, path[s][e]);
sprint(path[s][e] + , e);
}
}
} int main()
{
int N;
SCF(N);
cin.get();
int len = ;
int dp[][];
FOR(casenum, , N)
{
cin.get();
cin.getline(brackets, );
len = ;
for (len = ; brackets[len] != '\0'; len++); if (casenum)
printf("\n");
if (len == )
{
printf("\n");
continue;
}
FOR(i, , len)
{
FOR(j, , len)
dp[i][j] = ;
}
FOR(i, , len)
dp[i][i] = ;
int end = ; FOR(clen, , len)
{
FOR(start, , len - clen)
{
end = start + clen;
dp[start][end] = Infinity; if ((brackets[start] == '(' && brackets[end] == ')') || (brackets[start] == '[' && brackets[end] == ']'))
{
dp[start][end] = dp[start + ][end - ];
path[start][end] = -;
} for (int k = start; k < end; k++)
{
if (dp[start][end] > dp[start][k] + dp[k + ][end])
{
dp[start][end] = dp[start][k] + dp[k + ][end];
path[start][end] = k;
}
} }
}
sprint(, len - );
printf("\n");
} return ;
}