UVa 1626 (输出方案) Brackets sequence

正规括号序列定义为:

  • 空序列是正规括号序列
  • 如果S是正规括号序列,那么[S]和(S)也是正规括号序列
  • 如果A和B都是正规括号序列,则AB也是正规括号序列

输入一个括号序列,添加尽量少的括号使之成为正规括号序列,并输出最优方案,多解的话输出任意一个即可。

设d(i, j)表示字符串s[i]~s[j]至少添加的括号的数量,则转移如下:

  • S形如[S']或(S'),则转移到d(i+1, j-1)
  • 如果S至少有两个字符,将其分为AB,转移到min{d(i, j), d(A) + d(B)}

不管是否满足第一条都要尝试第二种转移,因为[][]可能经过第一条转移到][

 

打印的时候重新检查一下最优决策。

 1 //#define LOCAL

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <algorithm>

 5 using namespace std;

 6 

 7 const int maxn = 110;

 8 char s[maxn];

 9 int d[maxn][maxn], n;

10 

11 bool match(char a, char b)

12 {

13     return (a == '(' && b == ')') || (a == '[' && b == ']');

14 }

15 

16 void dp()

17 {

18     for (int i = 0; i < n; ++i)

19     {

20         d[i+1][i] = 0;    //对应空串

21         d[i][i] = 1;

22     }

23     for (int i = n-2; i >= 0; --i)

24     {

25         for (int j = i+1; j < n; ++j)

26         {

27             d[i][j] = n;

28             if(match(s[i], s[j]))

29                 d[i][j] = min(d[i][j], d[i+1][j-1]);

30             for (int k = i; k < j; ++k)

31                 d[i][j] = min(d[i][j], d[i][k] + d[k+1][j]);

32         }

33     }

34 }

35 

36 void print(int i, int j)

37 {

38     if(i > j)    return;

39     if(i == j)

40     {

41         if(s[i] == '(' || s[i] == ')')    printf("()");

42         else                            printf("[]");

43         return;

44     }

45     int ans = d[i][j];

46     if(match(s[i], s[j]) && ans == d[i+1][j-1])

47     {

48         printf("%c", s[i]);

49         print(i+1, j-1);

50         printf("%c", s[j]);

51         return;

52     }

53     for (int k = i; k < j; ++k)

54     {

55         if(ans == d[i][k] + d[k+1][j])

56         {

57             print(i, k);

58             print(k+1, j);

59             return;

60         }

61     }

62 }

63 

64 void readline(char* s)

65 {

66     fgets(s, maxn, stdin);

67 }

68 

69 int main(void)

70 {

71     #ifdef    LOCAL

72         freopen("1626in.txt", "r", stdin);

73     #endif

74     

75     int T;

76     readline(s);

77     sscanf(s, "%d", &T);

78     readline(s);

79     while(T--)

80     {

81         readline(s);

82         n = strlen(s) - 1;    //去掉最后的换行符 

83         memset(d, -1, sizeof(d));

84         dp();

85         print(0, n-1);

86         puts("");

87         if(T)    puts("");

88         readline(s);

89     }

90 

91     return 0;

92 }
代码君

 

你可能感兴趣的:(sequence)