括号配对计数
思路
经典的区间dp. 显然 \(dp[i][j]\) 表示将字符串的 \([i, j]\) 区间变合法的最少操作数.
\(i, j\) 没有配对时有:
\(dp[i][j] = \mathop{min\{dp[i][k] + dp[k + 1][j]\}}\limits_{i \leq k < j}\)
\(i, j\) 配对时有:
\(dp[i][j] = \mathop{min\{dp[i + 1][j - 1], min\{dp[i][k] + dp[k + 1][j]\}\}}\limits_{i \leq k < j}\)
注意初始时 \(dp[i][i] = 1(1 \leq i \leq n)\) 就好了.
代码
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0; char c = getchar(); bool f = 1;
while(c < '0' || c > '9') { if(c == '-') f = 0; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return (f ? x : -x);
}
const int N = 1e3 + 10, INF = 0x3f3f3f3f;
int n, dp[N][N];
char s[N];
int main() {
cin >> (s + 1);
n = strlen(s + 1);
for(int i = 1; i <= n; ++i) dp[i][i] = 1;
for(int l = 1; l < n; ++l) {
for(int i = 1; i <= n; ++i) {
int j = i + l;
dp[i][j] = INF;
if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);
for(int k = i; k < j; ++k)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
}
printf("%d\n", dp[1][n]);
return 0;
}

浙公网安备 33010602011771号