您的位置:首页 > 其它

POJ 2955 Brackets 【区间DP】

2016-05-25 16:50 351 查看
题目链接

题意

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

分析

状态

区间问题的一般处理方法:设dp[i][j]⇔与j间最长满足要求子串长度

状态转移方程

如果这个区间两个端点的括号是匹配的,那么它可以是由去掉两端点的串加上2转移而来,比如([])

dp[i][j]=max(dp[i][j],dp[i+1][j−1]+2)

它也可能是由它的两个串拼在一起而成的,比如()[]

dp[i][j]=max(dp[i][j],dp[i][i]+dp[i+1][j]→dp[i][j−1]+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 debug

int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj dp 区间DP