题目描述:给出一串由‘(‘)’‘ [ ' ' ] '组成的串,让你输出添加最少括号之后使得括号匹配的串。
思路:
i-j表示的是一条序列的开始和结束,dp[ i ][ j ]表示子串s[ i~j ] 需要添加的数量。
思想是不断分割小区间,当出现(X)时,应该转移到x,即从dp(i,j)转移到dp(i+1,j-1)
如果为单个字符,则dp[ i ][ j ] = 1;(i == j)
打印:算出最优的地方 1、如果可以直接往里转移,则 dp[ i ][ j ] == dp[ i+1 ][ j-1 ];把s[i]和s[j]打印了,再向里递归print(i+1, j-1);
2、s[i]!=s[j],则直接去找i-j之间的最优点k进行切分,然后递归
代码:
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
const int inf=0x3f3f3f3f;
string s;
int d[110][110],value[110][110],len;
void print(int i,int j){//递归输出
if(i>j) return;
else if(i==j){
if(s[i]==')'||s[i]=='(') printf("()");
if(s[i]==']'||s[i]=='[') printf("[]");
}
else if(value[i][j]==-1){
printf("%c",s[i]);
print(i+1,j-1);
printf("%c",s[j]);
}
else{
print(i,value[i][j]);
print(value[i][j]+1,j);
}
return;
}
int main(){
while(getline(cin,s)){
//注意整行读入,有可能是空格
memset(d,0,sizeof(d));
len=(int)s.length();
for(int i=0; i<=len; i++) d[i][i]=1;
for(int tem=1; tem<len; tem++){//
for(int i=0; i<=len-tem; i++){
int j=tem+i;
d[i][j]=inf;
if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']')){
d[i][j]=d[i+1][j-1];
value[i][j]=-1;//匹配标志
}
for(int k=i; k<j; k++){
if(d[i][j]>d[i][k]+d[k+1][j]){//更新i-j的最小答案
d[i][j]=d[i][k]+d[k+1][j];
value[i][j]=k;//找到中间更新的点
}
}
}
}
print(0,len-1);
printf("\n");
}
}