非特定方向计算中的动态编程方法

时间:2012-11-29 07:59:10

标签: algorithm dynamic-programming

我正在尝试解决Ball Removal problem on topcoder,在此处粘贴问题声明,因为需要登录才能访问此链接。


  

问题陈述

     

你有N个球,其中N是奇数。球的编号从0到N-1。按此顺序,它们被排列成从左到右的一行。

     

除了数字之外,每个球上都有“左”字或“右”字样。为简单起见,我们将使用字符'<'而不是“左”,而字符'>'而不是“正确”。您将在所有球上获得标签作为String标签。对于每个i,标签的字符i代表球i上的单词。

     

现在,您将重复以下步骤:

     
      
  • 选择一个不在球排两端的球。
  •   
  • 如果所选球的标签为'<',则将所选球和球直接移到球的左侧。否则,移除选定的球以及球右侧的球。
  •   
  • 如果不重新排序剩下的球,请将它们推到一起以消除上一步中产生的间隙。
  •   
     

当行中只剩下一个球时,该过程结束。那个球被称为幸存者。请注意,球过程中的数字不会改变。

     

找到所有可能的幸存者。您的方法必须返回一个包含N个字符的String。如果球我可以成为幸存者,则返回值的字符i必须为'o'(小写字母哦)。否则,相应的字符必须是'。' (一段时间)。

     

约束

     
      
  • 标签将包含3到49个字符(包括3和49个字符)。
  •   
  • 标签将包含奇数个字符。
  •   
  • 标签的每个字符都是'>'或'<'。
  •   
     

实例
  “<<>” 中   返回:“.. oo”

     

最初,你有三个球。由于你不能在行的末端选择球,你必须选择球1.由于它的标签是'<',你删除球0和1.因此唯一可能的幸存者是球2。   1)   “>>><<”   返回:“o ... o”

     

如果你首先选择球2或球3,你必须选择球1接下来,幸存者将是0球。如果你先选择球1,你必须选择球3接下来,幸存者将是球4。

     

2)   “<<><<”   返回:“.... o”

     

3)   “<><<><>” 中   返回:“o ..... o”

     

4)   “>>><<<>>>>><<<>” 中   返回:“o ..... o.o ..... o”


我正在考虑针对这个问题的动态编程方法,我想有一个布尔数组来标记哪些字符已被删除,然后找到下一个左边和下一个右边但是这使得该方法非常低效并且我必须写一个递归方法。为了实现动态编程方法,我需要维护一个状态。但我无法弄清楚我应该保持什么状态,在我的想法中,状态是当前字符串和当前索引的组合,但保持状态字符串对我来说似乎不正确。

我面临的另一个问题是,在这种情况下,如果我改变方向结果更改,我也没有特定的方向,如果我从左向右移动,我可能也需要从右向左移动。 请帮我找到解决这个问题的正确方法。

1 个答案:

答案 0 :(得分:1)

状态可以是布尔值 - DP[left][right][isLeftBoundary][isRightBoundary]

这意味着如果可以完全消除从left开始并在right结束的子字符串。

如果isLeftBoundary符号是字符串的最左边,则

left只是一个布尔标记。

如果isRightBoundary符号是字符串的最右边,则

right只是一个布尔标志。

如果DP[0][i - 1][1][0]DP[i + 1][N][0][1]true,则表示位置i的球可以保留。

    int canDelete(int l, int r, int st, int en)
    {
        if (l > r) return 1; //we succeeded in removing the whole string

        if (DP[l][r][st][en] != -1)
           return DP[l][r][st][en];

        int ans = 0;

        //i is the last removed ball, which will eliminate the whole string[l, r]
        for (int i = l + st; i <= r - en; i++) 
        {
            if (inp[i] == '<') //it will remove a ball to the left, but which one?
            {
                for (int j = l; j < i; j++) //ball i will remove ball j
                {       
                     if (canDelete(l, j - 1, st, 0) 
                      && canDelete(j + 1, i - 1, 0, 0) 
                      && canDelete(i + 1, r, 0, en))
                         ans = 1;       
                }
            }
            else
            if (inp[i] == '>') //it will remove a ball to the right, but which one?
            {
                for (int j = i + 1; j <= r; j++) //ball i will remove ball j
                {       
                     if (canDelete(l, i - 1, st, 0) 
                      && canDelete(i + 1, j - 1, 0, 0) 
                      && canDelete(j + 1, r, 0, en))
                         ans = 1;       
                }       
            }
        }

        return ans;
    }