路径记录,用a【i】【j】记录dp【i】【j】这个状态来源于哪里
思路:dp[i][j]表示从区间i到区间j使其所以括号匹配需要补上的最少括号数,那么当出现一个括号时,首先考虑它不与后面匹配的情况,那么需要加一个相对应的括号,让之匹配dp[i][j]=dp[i+1][j]+1;
然后再考虑,若是后面有括号可以让它匹配的情况,那么假设i<k<=j,当s[i]=='('&&s[k]==')'的时候,考虑动态转移,dp[i][j]=dp[i+1][k-1]+dp[k+1][j]
同时把a【i】【j】设为k,因为括号序列最少添加的括号就是,总括号数减去括号的最大匹配数,也就是我们只需用找出所有可以匹配的括号,以及他们对应括号,把他们设为匹配的,输出时,遇见匹配 的直接输出,没有匹配的加一个左括号或右括号。
///本题感觉还没有那么好,慢慢体会吧
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
char s[10009];
int f[1009][1009],a[1009][1009],n;
bool b[1009]={false};
void dw(int l,int r)
{
if (l>=r) return ;
if (a[l][r]==-1) dw(l+1,r);
else
{
b[l]=true;b[a[l][r]]=true;
dw(l+1,a[l][r]-1);
dw(a[l][r]+1,r);
}
}//标记是否匹配括号
int main()
{
while (gets(s))
{
n=strlen(s);
//if (n==0) {printf("\n");continue;}
memset(f,0,sizeof(f));
memset(a,-1,sizeof(a));
memset(b,false,sizeof(b));
for (int i=n-1;i>=0;i--)
{
f[i][i]=1;
for (int j=i+1;j<n;j++)
{
f[i][j]=f[i+1][j]+1;
for (int l=i+1;l<=j;l++)
if ((s[i]=='('&&s[l]==')')||(s[i]=='['&&s[l]==']'))
if (f[i][j]>f[i+1][l-1]+f[l+1][j])//方程
{
f[i][j]=f[i+1][l-1]+f[l+1][j];
a[i][j]=l;
}
}
}
dw(0,n-1);
for (int i=0;i<n;i++) if (b[i]) printf("%c",s[i]);
else if (s[i]=='('||s[i]==')') printf("()");else printf("[]");//如果没有匹配直接输出
printf("\n");
}
return 0;
}