POJ 2955 Brackets 题解

原题链接

题意:
给出一串由括号组成的字符串,只包括以下四种括号: ( ) [ ]
并且规定其中两两可以配对,但是必须是同一种括号(圆括号或方括号),并且左括号在左,右括号在右。例如((()))中就有3对配对的括号,或者说是有6个(单个的)匹配括号。当然,像([)]这种两种乱套在一起的括号,虽然在数量和顺序上没问题,但是因为不允许交叉,所以不算数。
现在请你求出每一个CASE中最多有几个配对括号。

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 5130 Accepted: 2753

从POJ的要求来看Time和Memory都不成什么问题

分析:
明摆着的区间动归,用dp[i][j]表示在第i和第j之间最大的匹配对数(注意我用的是对数),转移方程:
dp[i][j]={
if ( i>=r ) 0 //嘿小子,你越界了呦
else //合法的区间
begin
for k=i..j-1 do //枚举中间的分开点,分别DP看看两边最大能匹配多少
dp[i][j]:=max( dp[i][j],DP(i,k)+DP(k+1,j) )
if ( 第i和第j可以配对 ) //还要考虑下如果把这俩配成一对会咋样
dp[l][r]:=max( DP(l+1,r-1)+1,dp[l][r] )
end
}
好了,边界都含在里面了,接下来就是代码实现了。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=105;
int dp[maxn][maxn];
string s;
bool cmp(char l,char r){
    if(l=='('&&r==')')
        return true;
    if(l=='['&&r==']')
        return true;
    return false;
}
int DP(int l,int r){
    if(~dp[l][r])
        return dp[l][r];
    if(l>=r)
        return dp[l][r]=0;
    for(int k=l;k<r;k++)
        dp[l][r]=max(dp[l][r],DP(l,k)+DP(k+1,r));
    if(cmp(s[l],s[r]))
        dp[l][r]=max(DP(l+1,r-1)+1,dp[l][r]);
    return dp[l][r];
}
int main(){
    while(cin>>s&&s!="end"){
        memset(dp,-1,sizeof(dp));
        cout<<2*DP(0,s.length()-1)<<endl;
    }
    return 0;
} 

自我点评一下,转移方程写的可能有点乱,见谅吧,毕竟写了没几次。话说这编辑器里也预览不到缩进效果,于是space和Tab就随便上了。

By YOUSIKI

你可能感兴趣的:(poj)