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 ...
随机推荐
- POJ2096 Collecting Bugs(概率DP,求期望)
Collecting Bugs Ivan is fond of collecting. Unlike other people who collect post stamps, coins or ot ...
- poj 3525 求凸包的最大内切圆
Most Distant Point from the Sea Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3640 ...
- SGU104 二维dp
大致题意: n个东西放在(1.2.3...m)个容器中,先放的必需在后方的左边.a[i][j]表示i号物品放在j容器所得 的价值,求最大价值. 几乎是刚刚开始接触动态规划题,开始我这样想 每个东西一件 ...
- AC日记——最大子段和 洛谷 P1115
题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入输出格式 输入格式: 输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度. 第2行包含N个绝对值不大于10000 ...
- js判断手机的横竖屏调整样式
在移动端,我们经常遇到横竖屏的问题,所以我们改如何判断或针对横竖屏来写代码呢.首先需要在head中加入如下代码: <meta name="viewport" content= ...
- .net core webapi jwt 更为清爽的认证 ,续期很简单
我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下 jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于中间件,我的处理方式是将获取token放到api的一个具体的co ...
- vue之组件理解(一)
组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data.computed.watch.methods 以及生命周期钩子等.仅有的例外是像 el 这样根实例特有的选项. ...
- influxDB的安装和简单使用
单机的influxdb免费,集群的是收费的 1.安装,参考官方文档 https://portal.influxdata.com/downloads RedHat & CentOS: wget ...
- Html5培训之精髓
一.核心技术(可去各技术官网学习) 1.html5的六大核心技术:Html5,CSS3,JavaScript,WebSocket,PhoneGap,Node.js,它们覆盖了设备端,浏览器端和云端的开 ...
- Access 执行查询时,抛出“标准表达式中数据类型不匹配”的错误
Access根据时间查询时应在查询条件前后加# SELECT COUNT(*) FROM [User] WHERE [CreateTime] > #{0}#