题意:
寻找一种正确的括号匹配方案,并且打印出来。
思路:
1. 转移方程为:dp[i][j] = min(dp[i][k] + dp[k+1][j]); 如果 s[i] == s[j] 则还有 dp[i][j] = min(dp[i][j], dp[i+1][j-1]);
2. 因为涉及到打印路径,所以还要单独开辟一个数组出来,记录每次选择的结果。这也差不多是打印路径一类题定势的解题步骤;
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 110;
const int INFS = 0x3fffffff;
char s[MAXN];
int dp[MAXN][MAXN], choose[MAXN][MAXN];
void printstring(int i, int j) {
if (i > j)
return;
if (i == j) {
if (s[i] == '(' || s[i] == ')')
printf("()");
else
printf("[]");
} else if (choose[i][j] == -1) {
printf("%c", s[i]);
printstring(i + 1, j - 1);
printf("%c", s[j]);
} else {
printstring(i, choose[i][j]);
printstring(choose[i][j] + 1, j);
}
}
int main() {
while (gets(s)) {
int len = strlen(s);
for (int i = 0; i < len; i++)
dp[i][i] = 1, dp[i+1][i] = 0;
for (int p = 1; p < len; p++) {
for (int i = 0, j = i + p; j < len; i++, j++) {
dp[i][j] = INFS;
choose[i][j] = -1;
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++) {
if (dp[i][j] > dp[i][k] + dp[k+1][j]) {
choose[i][j] = k;
dp[i][j] = dp[i][k] + dp[k+1][j];
}
}
}
}
printstring(0, len - 1);
printf("\n");
}
return 0;
}