题目链接:
POJ 2955 Brackets
题意:
给出一个长度不超过100的只含
"(",")","[","]"
的字符串,求字符串中最大的匹配括号数。
(),[],(()),()[],()[()]
都可以认为是匹配的。
样例:
((()))
()()()
([]])
)[)(
([][][)
6
6
4
0
6
分析:
注意这里的括号匹配并不要求必须是连续的,可参考最后一个样例。
用
dp[i][j]
表示区间
i→j
的最大括号匹配数,如果进行区间更新,实际上我需要知道这个区间的任意子区间的最优解答案,首先考虑
s[i]和s[j]
能否匹配,然后枚举划分子区间的位置,这个位置应是
k∈[i,j)
,而不是
k∈(i,j)
,也不是
k∈[i,j]
。
状态转移方程;
dp[i][j]=dp[i+1][j−1]+2(if(s[i]和s[j]匹配)
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j])k∈[i,j)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 110;
char s[MAX_N];
int dp[MAX_N][MAX_N];
int main()
{
while(~scanf("%s", s)) {
if(strcmp(s, "end") == 0) break;
memset(dp, 0, sizeof(dp));
int len = strlen(s);
for(int i = len - 1; i >= 0; --i) {
for (int j = i + 1; j < len; ++j) {
if((s[i] == '(' && s[j] == ')') ||
(s[i] == '[' && s[j] == ']')) {
dp[i][j] = dp[i + 1][j - 1] + 2;
}
for(int k = i; k < j; ++k) {
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
}
}
printf("%d\n", dp[0][len - 1]);
}
return 0;
}