题意:
看白书
要点:
状态转移方程真难想,这基本上是个区间DP问题,但还得考虑首尾已经是正规的,这两种情况都要考虑,而且还互相干扰,最后还得打印解,基本就是重新检查一下哪个决策最好。还有个陷阱:输入串可能是空串,所以要用gets。
15546092 | Accepted | 4024K | 32MS | 1166B | 2016-05-24 14:57:43 |
#include#include #include #include using namespace std;char str[1000];int d[1000][1000];int n;bool match(char a, char b){ if ((a == '('&&b == ')')||(a == '['&&b == ']')) return true; return false;}void dp(){ int i, j, k, l; memset(d, 0, sizeof(d)); for (i = 0; i <= n; i++) d[i][i] = 1; //单字符为0 for (l = 2; l <= n; l++) { for (i = 0; i + l <= n; i++) { j = i + l-1; d[i][j] = 0x3f3f3f3f; if (match(str[i],str[j])) d[i][j] = min(d[i][j],d[i + 1][j - 1]); for (k = i; k <= j-1; k++) d[i][j] = min(d[i][j], d[i][k] + d[k+1][j]); } }}void print(int i, int j){ if (i > j) return; if (i == j) { if (str[i] == '(' || str[i] == ')') printf("()"); else printf("[]"); return; } int ans = d[i][j]; if (match(str[i], str[j]) && (ans == d[i + 1][j - 1])) { printf("%c", str[i]); print(i + 1, j - 1); printf("%c", str[j]); return; } for (int k = i; k <= j - 1; k++) { if (ans == d[i][k] + d[k + 1][j]) { print(i, k); print(k + 1, j); return; } }}int main(){ gets_s(str); n = strlen(str); dp(); print(0, n-1); printf("\n"); return 0;}