题解: dp [ i ] [ j ] 表示添加括号的个数, pos[ i][ j ] 表示 i , j 中哪个位置分开,使得两部分分别匹配。
pos [ i ][ j ] 为-1的时候,说明i, j 括号匹配。
初始值置dp [ i ] [ i ] = 1; 如果只有一个括号,那么匹配结果必然是差1。
首先判断括号是否匹配,如果匹配,那么dp [ i ] [ j ] = dp[ i + 1] [ j - 1] 。如此递推dp [ i ] [ j ] 的值。
然后判断dp [ i ] [ j ] = min ( dp [ i ] [ mid ] + dp [ mid + 1 ] [ j ]);
输出结果时采用递归方式输出print(0, len-1)输出函数定义为print(int i, int j),表示输出从下标i到下标j的合法序列
当i>j时,直接返回,不需要输出
当i==j时,d[i][j]为1,至少要加一个括号,如果s[i]为’(’ 或者’)’,输出"()",否则输出"[]"
当i>j时,如果c[i][j]>=0,说明从i到j断开了,则递归调用print(i, c[i][j]);和print(c[i][j]+1,j);
如果c[i][j]<0,说明没有断开,如果s[i]==’(’ 则输出’(’、 print(i+1, j-1); 和")",否则输出"[" print(i+1, j-1);和"]"
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=105;
char str[maxn];
int dp[maxn][maxn];
int path[maxn][maxn];
void oprint(int i,int j)
{
if(i>j)
return;
if(i==j)
{
if(str[i]=='['||str[i]==']')
{
printf("[]");
}
else
{
printf("()");
}
}
else if(path[i][j]==-1)
{
printf("%c",str[i]);
oprint(i+1,j-1);
printf("%c",str[j]);
}
else
{
oprint(i,path[i][j]);
oprint(path[i][j]+1,j);
}
}
int main()
{
while(gets(str))
{
int n=strlen(str);
memset(dp,0,sizeof(dp));
if(n==0)
{
printf("\n");
continue;
}
for(int i=0; i<n; i++)
{
dp[i][i]=1;
}
for(int r=1; r<n; r++)
{
for(int i=0; i<n-r; i++)
{
int j=i+r;
dp[i][j]=0x7fffffff;
if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']'))
{
dp[i][j]=dp[i+1][j-1];
path[i][j]=-1;
}
for(int k=i; k<j; k++)
{
if(dp[i][j]>dp[i][k]+dp[k+1][j])
{
dp[i][j]=dp[i][k]+dp[k+1][j];
path[i][j]=k;
}
}
}
}
oprint(0,n-1);
printf("\n");
}
}