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 ...
随机推荐
- MySql将查询结果插入到另外一张表
今天遇到一个业务需求是这样的:对在职员工超过55岁提醒.我想的思路是查询员工表,然后将超过55岁的人的信息存到另一个表,并且以消息的形式给用户提示,用户处理掉之后此消息失效(在数据库做标记). 不管是 ...
- .net core webapi jwt 更为清爽的认证 ,续期很简单
我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下 jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于中间件,我的处理方式是将获取token放到api的一个具体的co ...
- 2015多校联合训练赛 Training Contest 4 1008
构造题: 比赛的时候只想到:前面一样的数,后面 是类似1,2,3,4,5,6....t这 既是:t+1,t+1...,1,2,3,...t t+1的数目 可能 很多, 题解时YY出一个N 然后对N ...
- 第1章 SpringBoot 简介
一.什么是Spring Boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发 ...
- 关于时间,日期,星期,月份的算法(Java中Calendar的使用方法)
原文:http://www.open-open.com/code/view/1446195787257 package cn.outofmemory.codes.Date; import java.u ...
- Info.plist 的字段解释
bundle字段 这些字段名都是XML中的名称,在xcode的属性编辑器中,名字并不相同 bundle目录中的属性列表详细描述了有关该bundle的信息.Finder和一些系统API在一些情况下会使用 ...
- android DatePicker使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...
- 【Android开发—智能家居系列】(四):UDP通信发送指令
思路回顾 [1]手机连接WIFI模块 [2]UDP通信对WIFI模块发送指令,以和WIFI模块保持连接状态 [3]UDP通信对WIFI模块发送指令,让其搜索可用的无线网,返回WIFI列表 [4]发送指 ...
- STM8S---选项字节(Option Byte)写操作之IO复用
功能实现目标 通过对选项字节的写操作来实现TIM2的CH3通道的PWM输出IO复用.能够设置为PA3或者PD2输出. 通过STVP方式操作链接 选项字节 选项字节包含芯片硬件特性的配置和存储器 ...
- sshd登录攻击
先说简单的防范措施: 1.密码足够复杂 密码的长度大于8位.有数字.大小写字母.特殊字符组合. 2.nmap 扫描 为了避免被扫描到, #看到端口是81 ssh root@192.168.1.63 玩 ...