首页 > 代码库 > poj 1141 Brackets Sequence(区间DP)
poj 1141 Brackets Sequence(区间DP)
题目:http://poj.org/problem?id=1141
转载:http://blog.csdn.net/lijiecsu/article/details/7589877
定义合法的括号序列如下:
1 空序列是一个合法的序列
2 如果S是合法的序列,则(S)和[S]也是合法的序列
3 如果A和B是合法的序列,则AB也是合法的序列
例如:下面的都是合法的括号序列
(), [], (()), ([]), ()[], ()[()]
下面的都是非法的括号序列
(, [, ), )(, ([)], ([(]
给定一个由‘(‘, ‘)‘, ‘[‘, 和 ‘]‘ 组成的序列,找出以该序列为子序列的最短合法序列。
d[i][j]为输入序列从下标i到下标j最少需要加多少括号才能成为合法序列。0<=i<=j<len (len为输入序列的长度)。
c[i][j]为输入序列从下标i到下标j的断开位置,如果没有断开则为-1。
当i==j时,d[i][j]为1
当s[i]==‘(‘ && s[j]==‘)‘ 或者 s[i]==‘[‘ && s[j]==‘]‘时,d[i][j]=d[i+1][j-1]
否则d[i][j]=min{d[i][k]+d[k+1][j]} i<=k<j , c[i][j]记录断开的位置k
采用递推方式计算d[i][j]
输出结果时采用递归方式输出print(0, len-1)
输出函数定义为print(int i, int j),表示输出从下标i到下标j的合法序列
当i>j时,直接返回,不需要输出
当i==j时,d[i][j]为1,至少要加一个括号,如果s[i]为‘(‘ 或者‘)‘,输出"()",否则输出"[]"
当i>j时,如果c[i][j]>=0,说明从i到j断开了,则递归调用print(i, c[i][j]);和print(c[i][j]+1, j);
如果c[i][j]<0,说明没有断开,如果s[i]==‘(‘ 则输出‘(‘、 print(i+1, j-1); 和")" 否则输出"[" print(i+1, j-1);和"]"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <cstdio> #include <cstring> using namespace std; int dp[107][107]; int c[107][107]; char ch[107]; int len ; void mydp() { memset(dp,0, sizeof (dp)); memset(c,0, sizeof (c)); int i,j,k,l; for (i = 0; i < len; i++) dp[i][i] = 1; int min; for (l = 1; l < len; l++) for (i = 0; i+l < len; i++) { j = i+l; min=dp[i][i] + dp[i+1][j]; c[i][j] = i; for (k = i+1; k < j; k++) { if (dp[i][k]+dp[k+1][j] < min) { min = dp[i][k] + dp[k+1][j]; c[i][j] = k; } } dp[i][j] = min; if ( (ch[i] == ‘(‘ && ch[j] == ‘)‘ ) || (ch[i] == ‘[‘ && ch[j] == ‘]‘ ) ) { if (dp[i+1][j-1] < min){ dp[i][j] = dp[i+1][j-1]; c[i][j] = -1; } } } } void print( int i, int j) { if (i > j) return ; if (i == j) { if (ch[i]== ‘(‘ || ch[i] == ‘)‘ ) printf( "()" ); else printf( "[]" ); } else { if (c[i][j] >= 0) { print(i,c[i][j]); print(c[i][j]+1,j); } else { if (ch[i] == ‘(‘ ) { printf( "(" ); print(i+1,j-1); printf( ")" ); } else { printf( "[" ); print(i+1,j-1); printf( "]" ); } } } } void printdp() { for ( int i = 0; i < len; i++) { for ( int j = 0; j < len; j++) printf( "%d " ,dp[i][j]); printf( "\n" );} printf( "\n" ); for ( int i = 0; i < len; i++) { for ( int j = 0; j < len; j++) printf( "%d " ,c[i][j]); printf( "\n" );} } int main() { scanf( "%s" ,ch); len = strlen(ch); mydp(); // printdp(); print(0,len-1); printf( "\n" ); return 0; } |