hoj 1936 Brackets dp记忆化

此题跟之前的括号最小添加数目一样的做法,只不过某些地方稍加改动,可以看看前一篇的括号最小添加数

 

#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;

}

你可能感兴趣的:(rack)