首页 > 代码库 > ZOJ1463:Brackets Sequence(区间DP)
ZOJ1463:Brackets Sequence(区间DP)
Let us define a regular brackets sequence in the following way:
1. Empty sequence is a regular sequence.
2. If S is a regular sequence, then (S) and [S] are both regular sequences.
3. If A and B are regular sequences, then AB is a regular sequence.
For example, all of the following sequences of characters are regular brackets sequences:
(), [], (()), ([]), ()[], ()[()]
And all of the following character sequences are not:
(, [, ), )(, ([)], ([(]
Some sequence of characters ‘(‘, ‘)‘, ‘[‘, and ‘]‘ is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
Input
The input file contains at most 100 brackets (characters ‘(‘, ‘)‘, ‘[‘ and ‘]‘) that are situated on a single line without any other characters among them.
Output
Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
1
([(]
Sample Output
()[()]
关键在于输入与输出格式,神坑!
区间dp,dp[i][j]表示 区间 i 到j之间的匹配数,区间两端的 字符是否可以刚好匹配,若可以匹配 状态转移就多了一个 dp[i][j] = max(dp[i][k]+dp[k+1][j],dp[i+1][j-1]+1),若不能匹配就是dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]);
若是两端可以匹配的,而且两端匹配了导致的dp值最大那么就标记一下,mark[i][j] = -1,否则 就mark[i][j] = k,这样把所有区间都dp一遍,回头再用DFS寻找,若是两端匹配导致值最大的 那么就直接输出这个字符标记一下,继续往更小的区间去搜索,否则 就分开两个区间搜索 [i,k] [k+1,j]
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define up(i,x,y) for(i=x;i<=y;i++) #define down(i,x,y) for(i=x;i<=y;i++) #define mem(a,b) memset(a,b,sizeof(a)) #define w(a) while(a) char str[105]; int t,len,dp[105][105],mark[105][105],pos[105]; void dfs(int i,int j) { if(mark[i][j]==-1) { pos[i]=pos[j]=1; dfs(i+1,j-1); } else if(mark[i][j]>=0) { dfs(i,mark[i][j]); dfs(mark[i][j]+1,j); } return; } int main() { int l,i,j,k; scanf("%d%*c%*c",&t); while(t--) { gets(str); len=strlen(str); if(!len) { printf("\n"); if(t) printf("\n"); continue; } up(i,0,len-1) up(j,0,len-1) { mark[i][j]=-2; dp[i][j]=0; } mem(pos,0); i=j=l=0; w(l<len) { if(i==j) { i++,j++; if(j==len) i=0,l++,j=l; continue; } if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']')) { up(k,i,j-1) { if(dp[i][j]<dp[i][k]+dp[k+1][j]) { mark[i][j]=k; dp[i][j]=dp[i][k]+dp[k+1][j]; } } if(dp[i][j]<dp[i+1][j-1]+1) { mark[i][j]=-1; dp[i][j]=dp[i+1][j-1]+1; } } else { up(k,i,j-1) { if(dp[i][j]<dp[i][k]+dp[k+1][j]) { mark[i][j]=k; dp[i][j]=dp[i][k]+dp[k+1][j]; } } } i++,j++; if(j==len) { l++; i=0; j=l; } } dfs(0,len-1); up(i,0,len-1) { if(pos[i]==1) printf("%c",str[i]); else if(str[i]=='('||str[i]==')') printf("()"); else printf("[]"); } printf("\n"); if(t) { printf("\n"); getchar(); } } return 0; }