POJ 2955 Brackets 区间dp

按照合法匹配条件,找最大的匹配

一眼就是区间dp 也知道dp[i][j]表示i-j中最大的匹配

但是状态转移方程怎么写呢??

其实对于这个题,感觉有很多种写法,看过网上的各种各样的题解,强烈Orz~

思路:

还是倒着dp,更新dp[i][j],有两种情况

1:当前字符不在最佳匹配中,dp[i][j]=dp[i+1][j];

2:当前字符在最佳匹配中,dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+1][j]+2),前提条件是i位置和k位置匹配成功

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long LL;
int dp[105][105];
char s[105];
int main()
{
    while(~scanf("%s",s+1))
    {
       if(s[1]=='e')break;
       int n=strlen(s+1);
       memset(dp,0,sizeof(dp));
       for(int i=n-1;i>=1;--i)
       {
           for(int j=i+1;j<=n;++j)
           {
               dp[i][j]=dp[i+1][j];
               for(int k=i+1;k<=j;++k)
                if((s[i]=='('&&s[k]==')')||(s[i]=='['&&s[k]==']'))
                dp[i][j]=max(dp[i][j],dp[i+1][k-1]+dp[k+1][j]+2);
           }
       }
       printf("%d
",dp[1][n]);
    }
    return 0;
}
View Code

 我的习惯性区间dp写法(只是看着顺眼,上一种其实也行,我有强迫症)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long LL;
int dp[105][105];
char s[105];
int main()
{
    while(~scanf("%s",s+1))
    {
       if(s[1]=='e')break;
       int n=strlen(s+1);
       memset(dp,0,sizeof(dp));
       for(int k=1;k<n;++k)
       {
           for(int i=1;i+k<=n;++i)
           {
               dp[i][i+k]=dp[i+1][i+k];
               for(int j=i+1;j<=i+k;++j)
                if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
                dp[i][i+k]=max(dp[i][i+k],dp[i+1][j-1]+dp[j+1][i+k]+2);
           }
       }
       printf("%d
",dp[1][n]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5064851.html