动态规划的括号求解器的有效解决方案

时间:2017-10-18 19:34:57

标签: algorithm recursion dynamic-programming brackets icc

acm icpc北美限定符问题的括号问题是

由'('和')'组成的括号序列被定义为有效 如下:

  1. 空序列有效。
  2. 如果X是有效括号序列,则(X)是有效括号 序列
  3. 如果X和Y是有效括号序列,则连接 X和Y,Z = XY,是一个有效的括号序列。
  4. 例如,“(())”,“()()”和“(()())()”都是有效括号序列,而“(”和“())”是无效括号序列。

    你得到长度为n的教授的括号序列。但是,它目前可能无效。教授要求您通过执行最多一个段反转操作来检查是否可以使序列有效。也就是说,您可以选择两个基于1的索引l和r(1≤l≤r≤n)并使用闭区间[l,r]中的索引反转每个括号。反转后,左括号'('变为右括号')'和右括号')'成为左括号'('。

    你可以使“()”(“通过反转段[3,4]有效。你可以通过反转段[3,3]来使”())“有效,或者通过反转段[ 2,2]。但是,不存在可以反转以制作“)))的段(”有效。

    输入:
    输入包含一行,包含1到5 000个括号。

    输出:
    如果您可以通过执行最多一个段反转来使括号序列有效,则输出“可能”,否则输出“不可能”。

    样本输入1 :()))()))------>可能的 样本输入2 :))))(------>不可能 样本输入3 :()------>可能的

    第18页的icpc solution 2016解释了该解决方案。 解决方案是

      
        
    • 让s1 ,. 。 。 ,sn表示括号的顺序。
    •   
    • 表征有效括号序列的另一种方法:      
          
      • Cond 1.对于序列的每个前缀,左括号至少与右括号一样多,并且
      •   
      • Cond 2.整个序列中有相同数量的左右括号
      •   
    •   
    • 基本理念:      
          
      • 在某些时候开始反转括号。稍后,停止反转括号
      •   
      • 在每一步中,确保左括号至少与右括号一样多(条件1)
      •   
      • 最后,确保左右括号(条件2)
      • 的数量相同   
    •   
    • 如何决定何时开始/停止反转?动态编程      
          
      • 设dp(i,l,t)为iff。它可以逐步完成。 。 。假设l,则sn满足条件1和2   是到目前为止我们看到的左括号的数量,和      
            
        • t =之前如果我们还没有开始反转括号,
        •   
        • t =如果我们当前正在反转括号,则反转,
        •   
        • t =如果我们停止反转括号
        • 之后   
      •   
      • 请注意,i - 1 - l是我们到目前为止看到的右括号的数量。
      •   
    •   
    • 复发:      
    •   
    • 答案是dp(1,0,之前)。
    •   

    我实现了这段代码。我将所有重复的值存储在散列映射中,其中键是序列索引,左括号计数,t(之前,反转或之后),值为true / false。并且使用hashmap中的值存在。但是,我的代码无法通过Kattis平台的测试用例。如何在这里更有效地应用动态编程

1 个答案:

答案 0 :(得分:0)

在这个问题中,n是5000,所以n ^ 2是2500万,你需要注意常数因子。

如果您可以直接索引结果数组而不是依赖于hashmap,通常会更快。困难在于确保索引中没有冲突。

在这种情况下,如果我们将(pos,count,t)作为键,那么简单地使用由index = pos * 5000 + count索引的字节数组应该比hashmap快得多。每个索引都有3个真/假值存储,因此可以存储在每个字节的最后3位。