此题跟之前的括号最小添加数目一样的做法,只不过某些地方稍加改动,可以看看前一篇的括号最小添加数
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
#define X 210
#define INF 1000
string s;
int dp[X][X];
int f(int i,int j) //记忆化dp
{
if(dp[i][j]!=-1) //如果已经算过,直接结束
return dp[i][j];
else if(i>=j)
return 0;
int ans = -1; //要算的是最大匹配括号,应该为-1
if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
ans = max(ans,f(i+1,j-1)+1);//目前已经匹配了,加一再与ans比较大小
else if(s[i]=='['||s[i]=='(')
ans = max(ans,f(i+1,j-1)); //如果是左括号,则左指针右移
else if(s[j]==']'||s[j]==')')
ans = max(ans,f(i,j-1)); //如果是右指针,则右指针右移
for(int k=i;k<j;k++) //相当于最短路中的松弛操作
ans = max(ans,f(i,k)+f(k+1,j));
dp[i][j] = ans; //借助辅助数组储存状态,用空间换时间
return ans;
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
while(getline(cin,s),s!="end")
{
memset(dp,-1,sizeof(dp));
if(s.size())
cout<<2*f(0,s.size()-1)<<endl;
else
cout<<endl;
}
return 0;
}