標籤:
題目描述:
定義合法的括弧序列如下:
1 空序列是一個合法的序列
2 如果S是合法的序列,則(S)和[S]也是合法的序列
3 如果A和B是合法的序列,則AB也是合法的序列
例如:下面的都是合法的括弧序列
(), [], (()), ([]), ()[], ()[()]
下面的都是非法的括弧序列
(, [, ), )(, ([)], ([(]
給定一個由‘(‘, ‘)‘, ‘[‘, 和 ‘]‘ 組成的序列,找出以該序列為子序列的最短合法序列。
思路:真是經典的題目,區間DP,題目居然有陷阱,輸入可能是空串,所以用scanf的時候,會不讀入,就少了一次讀入,wa
所以用gets
//AcceptedC++1.0022015-03-12 13:34:47#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int inf= 0x3f3f3f3f;int dp[105][105];char str[105];int n;bool match(char a,char b){ if(a=='('&&b==')') return true; else if(a=='[' && b==']') return true; return false;}void print(int l,int r) //遞迴列印解{ if(l>r) return ; if(l==r) { if(str[l]=='('||str[l]==')') printf("()"); else if(str[l]=='['||str[l]==']') printf("[]"); return ; } if(match(str[l],str[r])&&dp[l][r]==dp[l+1][r-1]) //別忘了match(str[l],str[r]),因為dp[l][r]==dp[l+1][r-1]時候,不一定外側括弧匹配,很容易錯 { putchar(str[l]); print(l+1,r-1); putchar(str[r]); return ; } for(int k=l;k<r;k++) if(dp[l][r]==dp[l][k]+dp[k+1][r]) { print(l,k); print(k+1,r); return; }}int main(){ int T; scanf("%d",&T); getchar();//吃掉T之後的換行 while(T--) { getchar(); //每個輸入前都有一個空行 gets(str+1); n=strlen(str+1); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) dp[i][i]=1; //邊界 for(int l=1;l<n;l++) for(int p=1;p+l<=n;p++) { dp[p][p+l] = inf ; if(match(str[p],str[p+l])) dp[p][p+l]=dp[p+1][p+l-1]; for(int k=p ; k<p+l ;k++) dp[p][p+l]=min(dp[p][p+l],dp[p][k]+dp[k+1][p+l]); } if(n) print(1,n); puts(""); if(T) putchar('\n'); //輸出之間要輸出空行 } return 0;}
UVA1626 - Brackets sequence(區間DP--括弧匹配+遞迴列印)