POJ 2955 Brackets
如果s[st] == s[ed],那么dp[st][ed] = dp[st + 1][ed - 1] + 2。(这个放在枚举断点之前)其实想想确实是这样的,两端相等,那么就该初始化为去头去尾的中间的子串的dp值再加上2
然后就开始枚举断点,更新dp为尽可能的大,大区间等于两个小区间相加
区间DP的一般步骤:
枚举长度
枚举起点
枚举断点(更新dp)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <limits>
#include <set>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 100 + 5;
string s;
int dp[maxN][maxN];
void init()
{
memset(dp, 0, sizeof(dp));
}
int main()
{
while(cin >> s)
{
if(s == "end")
break;
int n = s.size();
init();
for(int len = 2; len <= n; len ++ )//枚举长度
{
for(int st = 0; st < n; st ++ )//枚举起点
{
int ed = st + len - 1;
if(ed >= n) break;
int add = 0;
if(s[st] == '(' && s[ed] == ')')
add ++;
if(s[st] == '[' && s[ed] == ']')
add ++;
if(add)
dp[st][ed] = dp[st + 1][ed - 1] + 2;
for(int mid = st; mid <= ed - 1; mid ++ )//枚举断点
{
dp[st][ed] = max(dp[st][ed], dp[st][mid] + dp[mid + 1][ed]);
}
}
}
printf("%d\n", dp[0][n - 1]);
}
return 0;
}