UVA - 1626
Brackets sequence
|
The question is from here.
My Solution
类似于 triangulation 三角剖分的dp经典
如果是[。。]或(。。)这样的向里面转移 dp[ i ][ j ] = min(dp[ i [ j ], dp[ i+1 ][ j-1 ]);
如是是不同的则开始找点k ,必然存在一个k,使得 i - k - j得到一个最小值,即 d[ i ][ j ] = min(d[ i ][ j ], d[ i ][ k ]+d[ k+1 ][ j ];
边界: 为空是 d[ i ][ j ] = 0; (i > j) 转移的时候如果到了 i,i+1 再往里转移一次就 i+1,i 了 也就是这是如果为情况1则d[ i ][ j ] =0;
或者为单个字符 d[ i ][ j ] = 1;(i == j)
打印:再算出最优的地方 1、如果可以直接往里转移,则 d[ i ][ j ] == d[ i+1 ][ j-1 ];把这个打印了,再向里递归;
2、如果是情况2则直接去找那个k进行切分,然后递归
#include <iostream> #include <cstdio> #include <cstring> //#define LOCAL using namespace std; int d[104][104],n; char s[104]; bool match(char a, char b) { if(a == '(' && b == ')') return true; if(a == '[' && b == ']') return true; return false; } void dp() { for(int i = 0; i < n; i++) { d[i+1][i] = 0; d[i][i] = 1; } for(int i = n-2; i >= 0; i--){ for(int j = i+1; j < n; j++){ d[i][j] = n; if(match(s[i],s[j])) d[i][j] = min(d[i][j],d[i+1][j-1]); for(int k = i; k < j; 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(s[i] == '(' || s[i] == ')') printf("()"); else printf("[]"); return; } int ans = d[i][j]; if(match(s[i],s[j]) && ans == d[i+1][j-1]){ printf("%c", s[i]);print(i+1,j-1);printf("%c", s[j]); return; } for(int k = i; k < j; k++){ if(ans == d[i][k]+d[k+1][j]){ print(i,k);print(k+1,j); return; //即使有多个情况也只要打印一种,一般是选第一种或最后一种吧 //重写前,也就是最开始写这里的if子块掉了一对大括号,重写AC后又找了好久,才找出来这个bug } } } int main() { #ifdef LOCAL freopen("a.txt","r",stdin); #endif // LOCAL int T; scanf("%d", &T);getchar(); while(T--){ gets(s); gets(s); n = strlen(s); dp(); print(0,n-1); printf("\n"); if(T) printf("\n"); } return 0; }
最开始写的一直WA,后来实在不行了,重写吧,重写了就AC,然后对着找找bug又找了好久,真是迷啊
Thank you!