◆练习题目◆◇区间动态规划◇ Brackets

来源:互联网 发布:linux 自动挂载硬盘 编辑:程序博客网 时间:2024/06/08 12:15

◇区间动态规划◇ Brackets


Description
We give the following inductive definition of a “regular brackets” sequence:
the empty sequence is a regular brackets sequence,if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and if a and b are regular brackets sequences, then ab is a regular brackets sequence.no other sequence is a regular brackets sequence.
For instance, all of the following character sequences are regular brackets sequences:

(), [], (()), ()[], ()[()]

while the following character sequences are not:

(, ], )(, ([)], ([(]

Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1, i2, …, im where 1 ≤ i1 < i2 < … < im ≤ n, ai1ai2 … aim is a regular brackets sequence.
Given the initial sequence ([([]])], the longest regular brackets subsequence is [([])].

Input
The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters (, ), [, and ]; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.

Output
For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.

Sample Input

((()))()()()([]]))[)(([][][)end

Sample Output

66406

题目大意
给定一个括号序列,包含‘(’、‘)’、‘[’和‘]’。找到一个最长的序列(中间可以断开),使该序列中的每一个括号都匹配,输出该序列的长度。
题目有多组数据,每行一组,以“end”结束。


题目解析
这道题其实和另一道题很相像(不是打广告Brackets Sequence),而且似乎更加简单。同样是使用记忆化搜索
1. 状态

g[x][y]表示在原序列中从x到y的最长序列的长度

由于g[x][y]可能会为0(比如“()[]”),所以为了避免重复计算,我们可以用bool类型的f数组与g数组一一对应,表示该元素是否计算过;或将g数组初始化为-1,只要值不是-1,就表示计算过
2. 状态转移方程式
很显然,若序列A和序列B都是完全匹配的括号序列,那么A与B相接(AB)也应该是一个完全匹配的括号序列;同样,若序列S是完全匹配的括号序列,则在S左右各添加一个匹配的括号(如 (S) 和 [S])所得序列也是完全匹配的
因此,我们要分两种情况——“第x个和第y个元素是一对匹配的括号”和“第x个和第y个元素不是一对匹配的括号”:
针对第一种情况,我们就是利用“(S)和[S]”来判断,此时左右括号匹配,则总长度+1,并找到序列S的最长匹配序列长度
针对第二种情况,我们利用“AB”来判断,因此就要找到分段点,即在x~y之间枚举断开点k。找到最大的 g[x][k]+g[k+1][y]。
综合一下:

g[x][y]=2+g[x+1] [y-1] (元素x与元素y匹配)
g[x][y]=max(g[x][k]+g[k+1][x],g[x][y]) |(x<=k<=y)

注意情况2是必须考虑的,举个简单的例子—— “()()” 。若单单只考虑情况一,则只得到2,而正确答案是——4。


样例程序

/*Lucky_Glass*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int g[105][105];bool f[105][105];char s[105];int G(int x,int y){    if(f[x][y]) return g[x][y];    f[x][y]=true;    if(((s[x]=='(' && s[y]==')') || (s[x]=='[' && s[y]==']')) ) g[x][y]=G(x+1,y-1)+2;    for(int i=x;i<y;i++)        g[x][y]=max(g[x][y],G(x,i)+G(i+1,y));    return g[x][y];}int main(){    while(true)    {        memset(g,0,sizeof(g));        memset(f,0,sizeof(f));        scanf("%s",s);        if(strcmp(s,"end")==0)            break;        printf("%d\n",G(0,strlen(s)-1));    }    return 0;}

The End

Thanks for reading!

-Lucky_Glass