题目链接:https://vjudge.net/problem/POJ-2955

Brackets
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9630   Accepted: 5131

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 i1i2, …, im where 1 ≤ i1 < i2 < … < im ≤ nai1ai2 … 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

6
6
4
0
6

Source

题解:

求最多有多少对括号匹配。典型的区间dp。

方法一:

1.如果区间[l,r]的两端匹配,则左右各缩进一格,从而转化成处理[l+1, r-1]的区间。

2.不管是否符合条件1,都尝试去枚举分割点,使得整个区间分成两半,这样就可以把大区间的处理转化成两个小区间的处理。

记忆化搜索:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = +; char s[MAXN];
int dp[MAXN][MAXN]; int dfs(int l, int r)
{
if(r<=l) return ;
if(dp[l][r]!=-) return dp[l][r]; if( (s[l]=='('&&s[r]==')')||(s[l]=='['&&s[r]==']') ) //如果两端匹配,则可以缩减范围
dp[l][r] = dfs(l+, r-) + ;
for(int k = l; k<r; k++) //枚举分割点,分成两半
dp[l][r] = max(dp[l][r], dfs(l, k)+dfs(k+, r)); return dp[l][r];
} int main()
{
while(scanf("%s", s+) && strcmp(s+, "end"))
{
memset(dp, -, sizeof(dp));
cout<< dfs(, strlen(s+))* <<endl;
}
}

递推:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = +; char s[MAXN];
int dp[MAXN][MAXN]; int main()
{
while(scanf("%s", s+) && strcmp(s+, "end"))
{
memset(dp, , sizeof(dp));
int n = strlen(s+);
for(int len = ; len<=n; len++)
{
for(int l = ; l<=n-len+; l++)
{
int r = l+len-;
if( (s[l]=='('&&s[r]==')') || (s[l]=='['&&s[r]==']') )
dp[l][r] = dp[l+][r-] + ;
for(int k = l; k<r; k++)
dp[l][r] = max(dp[l][r], dp[l][k]+dp[k+][r]);
}
}
printf("%d\n", dp[][n]*);
}
return ;
}

方法二:

1.可知一个符号最多只能与一个符号匹配,那么对于当前的符号,我们就枚举其他符号与其匹配(不管是能匹配成功)。

2.假设区间为 [l, r],为l枚举匹配符号,当枚举到k位置时,就把区间分割成了两部分:[l+1, k-1] 和 [k+1, r] 。从而就把大区间的求解转化为小区间的求解。

记忆化搜索:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = +; char s[MAXN];
int dp[MAXN][MAXN]; int dfs(int l, int r)
{
if(r<=l) return ;
if(dp[l][r]!=-) return dp[l][r]; dp[l][r] = dfs(l+, r);
for(int k = l+; k<=r; k++)
{
int ismatch = (s[l]=='('&&s[k]==')')||(s[l]=='['&&s[k]==']');
int tmp = dfs(l+, k-)+dfs(k+, r)+ismatch;
dp[l][r] = max(dp[l][r], tmp);
}
return dp[l][r];
} int main()
{
while(scanf("%s", s+) && strcmp(s+, "end"))
{
memset(dp, -, sizeof(dp));
cout<< dfs(, strlen(s+))* <<endl;
}
}

递推:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = +; char s[MAXN];
int dp[MAXN][MAXN]; int main()
{
while(scanf("%s", s+) && strcmp(s+, "end"))
{
memset(dp, , sizeof(dp));
int n = strlen(s+);
for(int len = ; len<=n; len++)
{
for(int l = ; l<=n-len+; l++)
{
int r = l+len-;
dp[l][r] = dp[l+][r];
for(int k = l+; k<=r; k++)
{
int ismatch = (s[l]=='('&&s[k]==')')||(s[l]=='['&&s[k]==']');
dp[l][r] = max(dp[l][r], dp[l+][k-]+dp[k+][r]+ismatch);
}
}
}
printf("%d\n", dp[][n]*);
}
return ;
}

POJ2955 Brackets —— 区间DP的更多相关文章

  1. poj2955 Brackets (区间dp)

    题目链接:http://poj.org/problem?id=2955 题意:给定字符串 求括号匹配最多时的子串长度. 区间dp,状态转移方程: dp[i][j]=max ( dp[i][j] , 2 ...

  2. Codeforces 508E Arthur and Brackets 区间dp

    Arthur and Brackets 区间dp, dp[ i ][ j ]表示第 i 个括号到第 j 个括号之间的所有括号能不能形成一个合法方案. 然后dp就完事了. #include<bit ...

  3. POJ 2995 Brackets 区间DP

    POJ 2995 Brackets 区间DP 题意 大意:给你一个字符串,询问这个字符串满足要求的有多少,()和[]都是一个匹配.需要注意的是这里的匹配规则. 解题思路 区间DP,开始自己没想到是区间 ...

  4. POJ2955:Brackets(区间DP)

    Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...

  5. CF149D. Coloring Brackets[区间DP !]

    题意:给括号匹配涂色,红色蓝色或不涂,要求见原题,求方案数 区间DP 用栈先处理匹配 f[i][j][0/1/2][0/1/2]表示i到ji涂色和j涂色的方案数 l和r匹配的话,转移到(l+1,r-1 ...

  6. Brackets(区间dp)

    Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3624   Accepted: 1879 Descript ...

  7. poj 2955"Brackets"(区间DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 给你一个只由 '(' , ')' , '[' , ']' 组成的字符串s[ ], ...

  8. HOJ 1936&POJ 2955 Brackets(区间DP)

    Brackets My Tags (Edit) Source : Stanford ACM Programming Contest 2004 Time limit : 1 sec Memory lim ...

  9. Code Forces 149DColoring Brackets(区间DP)

     Coloring Brackets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

随机推荐

  1. 洛谷 P1095 守望者的逃离

    题目描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上.为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会 ...

  2. Perl语言入门--1--perl的包安装

    A.  手工安装 从CPAN下载了DBI模块1.13版的压缩文件DBI-1.13.tar.gz.假设放在/usr/local/src(一般需要编译安装的软件,都放在此目录下安装). # cd /usr ...

  3. linux下二机制文件的查看和编辑

    linux下很多命令都是二机制:/bin/下的各种命令---/bin/sh./bin/cat./bin/dmesg./bin/hostname等 如何查看这些二机制文件: xxd.hexdump 参考 ...

  4. 单点登录CAS-Demo

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 1安全证书配置 2部署服务端CAS-Server 3部署CAS-Client 4测试SSO   1,安全证书配置 CAS默认 ...

  5. 转: NetBean远程开发的格式与过程

    1. 介绍远程3种模式 https://netbeans.org/kb/docs/cnd/remote-modes.html 评注:英文的,3种模式讲的非常到位.服务器开发还是全远程比较不错.

  6. mysql 同样内容的字段合并为一条的方法

    从两个表中内联取出的数据,当中category_name字段有同样内容,想将具有同样内容的字段进行合并,将amount字段进行加法运算,变成下表中的内容 url=http%3A%2F%2Fdev.my ...

  7. go test test & benchmark

    开发程序其中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早 ...

  8. TListView使用方法1(转)

    ListView1.Items 为标准 Tlistitems类 ListView1.Items (1)赋值 with ListView1.Items.Add do begin Caption:=cap ...

  9. C语言-计数排序

    计数排序的基本思想是:统计一个数序列中小于某个元素a的个数为n,则直接把该元素a放到第n+1个位置上.当然当过有几个元素相同时要做适当的调整,因为不能把所有的元素放到同一个位置上.计数排序假设输入的元 ...

  10. INAPP

    1. Login API : 接口為您提供了我們的登入服務,可以讓使用者透過facebook帳號登入我們的服務,在您呼叫此API後,可以得到 使用者的UUID(Unique UID為使用者在平台的唯一 ...