POJ 2955 Brackets 【区间DP】

来源:互联网 发布:手机淘宝尺寸怎么设置 编辑:程序博客网 时间:2024/05/29 03:37

题目链接

题意

给一串包含中括号和小括号的字符串,求其括号匹配正常的顺序(不一定连续)子串中的(最长串)

分析

状态

区间问题的一般处理方法:设dp[i][j]j

状态转移方程

  1. 如果这个区间两个端点的括号是匹配的,那么它可以是由去掉两端点的串加上2转移而来,比如([])
    dp[i][j]=max(dp[i][j],dp[i+1][j1]+2)
  2. 它也可能是由它的两个串拼在一起而成的,比如()[]
    dp[i][j]=max(dp[i][j],dp[i][i]+dp[i+1][j]dp[i][j1]+dp[j][j])

初始化

这题数据量小,可以记忆化搜索,就不用考虑初始化的问题。
如果递推的话,先全部初始化为零,然后把相邻位置且匹配的区间初始化为2即可。

DP顺序

记忆化搜索不用说。递推时,观察状态转移方程,两个端点都在动,然而可以确定的是,状态转移依赖的区间的长度都比待求的小。因此可以以区间长度递增为DP顺序(从长度为3开始)。

最终解

自然是dp[0][n]

AC代码

//POJ 2955 Brackets//AC 2016-5-25 16:20:35//DP#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cctype>#include <cstdlib>#include <cstring>#include <vector>#include <set>#include <string>#include <map>#include <queue>#include <deque>#include <list>#include <sstream>#include <stack>using namespace std;#define cls(x) memset(x,0,sizeof x)#define inf(x) memset(x,0x3f,sizeof x)#define neg(x) memset(x,-1,sizeof x)#define ninf(x) memset(x,0xc0,sizeof x)#define st0(x) memset(x,false,sizeof x)#define st1(x) memset(x,true,sizeof x)#define INF 0x3f3f3f3f#define lowbit(x) x&(-x)#define bug cout<<"here"<<endl;//#define debugint dp[110][110];char seq[110];bool thesame(int a,int b){    char &l=seq[a],&r=seq[b];    if(l=='('&&r==')')        return 1;    if(l=='['&&r==']')        return 1;    return 0;}int dyna(int a,int b){    if(dp[a][b]==-1)    {        if(a>=b)            dp[a][b]=0;        else        {            for(int i=0;a+i<b;++i)                dp[a][b]=max(dp[a][b],dyna(a,a+i)+dyna(a+i+1,b));            if(thesame(a,b))                dp[a][b]=max(dp[a][b],dyna(a+1,b-1)+2);        }    }    return dp[a][b];}int main(){    #ifdef debug        freopen("E:\\Documents\\code\\input.txt","r",stdin);        freopen("E:\\Documents\\code\\output.txt","w",stdout);    #endif    while(scanf("%s",seq)!=EOF&&seq[0]!='e')    {        neg(dp);        printf("%d\n",dyna(0,strlen(seq)-1));    }    return 0;}
0 0