POJ2955 Brackets —— 区间DP
题目链接:https://vjudge.net/problem/POJ-2955
| 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 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
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的更多相关文章
- poj2955 Brackets (区间dp)
题目链接:http://poj.org/problem?id=2955 题意:给定字符串 求括号匹配最多时的子串长度. 区间dp,状态转移方程: dp[i][j]=max ( dp[i][j] , 2 ...
- Codeforces 508E Arthur and Brackets 区间dp
Arthur and Brackets 区间dp, dp[ i ][ j ]表示第 i 个括号到第 j 个括号之间的所有括号能不能形成一个合法方案. 然后dp就完事了. #include<bit ...
- POJ 2995 Brackets 区间DP
POJ 2995 Brackets 区间DP 题意 大意:给你一个字符串,询问这个字符串满足要求的有多少,()和[]都是一个匹配.需要注意的是这里的匹配规则. 解题思路 区间DP,开始自己没想到是区间 ...
- POJ2955:Brackets(区间DP)
Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...
- CF149D. Coloring Brackets[区间DP !]
题意:给括号匹配涂色,红色蓝色或不涂,要求见原题,求方案数 区间DP 用栈先处理匹配 f[i][j][0/1/2][0/1/2]表示i到ji涂色和j涂色的方案数 l和r匹配的话,转移到(l+1,r-1 ...
- Brackets(区间dp)
Brackets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3624 Accepted: 1879 Descript ...
- poj 2955"Brackets"(区间DP)
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 给你一个只由 '(' , ')' , '[' , ']' 组成的字符串s[ ], ...
- HOJ 1936&POJ 2955 Brackets(区间DP)
Brackets My Tags (Edit) Source : Stanford ACM Programming Contest 2004 Time limit : 1 sec Memory lim ...
- Code Forces 149DColoring Brackets(区间DP)
Coloring Brackets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
随机推荐
- 洛谷 P1095 守望者的逃离
题目描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上.为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会 ...
- Perl语言入门--1--perl的包安装
A. 手工安装 从CPAN下载了DBI模块1.13版的压缩文件DBI-1.13.tar.gz.假设放在/usr/local/src(一般需要编译安装的软件,都放在此目录下安装). # cd /usr ...
- linux下二机制文件的查看和编辑
linux下很多命令都是二机制:/bin/下的各种命令---/bin/sh./bin/cat./bin/dmesg./bin/hostname等 如何查看这些二机制文件: xxd.hexdump 参考 ...
- 单点登录CAS-Demo
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 1安全证书配置 2部署服务端CAS-Server 3部署CAS-Client 4测试SSO 1,安全证书配置 CAS默认 ...
- 转: NetBean远程开发的格式与过程
1. 介绍远程3种模式 https://netbeans.org/kb/docs/cnd/remote-modes.html 评注:英文的,3种模式讲的非常到位.服务器开发还是全远程比较不错.
- mysql 同样内容的字段合并为一条的方法
从两个表中内联取出的数据,当中category_name字段有同样内容,想将具有同样内容的字段进行合并,将amount字段进行加法运算,变成下表中的内容 url=http%3A%2F%2Fdev.my ...
- go test test & benchmark
开发程序其中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早 ...
- TListView使用方法1(转)
ListView1.Items 为标准 Tlistitems类 ListView1.Items (1)赋值 with ListView1.Items.Add do begin Caption:=cap ...
- C语言-计数排序
计数排序的基本思想是:统计一个数序列中小于某个元素a的个数为n,则直接把该元素a放到第n+1个位置上.当然当过有几个元素相同时要做适当的调整,因为不能把所有的元素放到同一个位置上.计数排序假设输入的元 ...
- INAPP
1. Login API : 接口為您提供了我們的登入服務,可以讓使用者透過facebook帳號登入我們的服務,在您呼叫此API後,可以得到 使用者的UUID(Unique UID為使用者在平台的唯一 ...