计算船上所有零件离开所需步骤数量的算法

时间:2018-09-22 15:56:15

标签: algorithm

我有问题:

  

在6x6的板上,您最多可以收到6件。
     作品由其位置以及在不改变方向的情况下移动的方向(方向:上,下,左,右)定义。
     每次迭代都可以移动任意数量的片段,但在迭代结束时只能占据一个方块。      如果两个零件的方向相反,则它们一旦接触就可以彼此通过(它们交换位置)。      如果一个片段最后在一个正方形上,并且在相同的迭代中一个片段将从该正方形离开,则也允许该片段。      在几次迭代(最短的时间)内,所有部分都将在电路板之外。

我尝试过以这种方式进行操作:

  1. 接收每件作品的位置
  2. 在第一个列表中的每个动作中创建所有可能的动作,将其移动到新动作的列表中,即移动一个,...,移动所有物件
  3. 删除旧动作,因为这些动作不会重复。
  4. 检查创建的每个举动是否可以完成,然后将其重新添加到举动池中。
  5. 从第2步开始重复。

此解决方案的问题是它非常耗时,因此无法正常工作。我目前不知道如何解决该问题。

1 个答案:

答案 0 :(得分:2)

第二步将检查每次迭代的2 6 个动作组合(如果板上有6个棋子),即对每个棋子是否移动都做是/否决定。

通常,这些组合中的许多组合都是无效的,因为它们会让两个片段占据相同的正方形。而且,某些组合将移动一件作品,而该作品实际上并不妨碍任何其他作品,因此不移动它不会有任何好处。在您的列表中放入这样的星座会拖延进程,而无济于事。

如果能够识别出几种模式,该算法将会有所改进:

  1. 如果某些零件放置在一个循环中,即它们都移动到该循环中“下一个”零件的位置,那么它们应该立即移动。

    示例:

    ┌───┬───┐
    │ → | ← |
    └───┴───┘
    

    或者:

    ┌───┬───┬───┐
    │ ↓ | ← | ← |
    ├───┼───┼───┤
    │ → | → | ↑ |
    └───┴───┴───┘
    

    尝试仅移动这些移动的子集是没有用的:仅在同一迭代中全部移动它们是有效的。此外,由于他们不会占用之前没有空的正方形(并且可能会阻塞另一个块),因此绝对没有理由延迟组合移动。因此,如果检测到此模式,则所有涉及的零件都应移动。

  2. 如果一块将移动到当前没有其他块或将不能移动到的正方形,则没有理由不进行移动。应该做的。

  3. 当一块可以移动到其他块也可以移动到的正方形时,则有必要考虑所有这些可能性,即考虑迭代选择,其中一个块可以移动到那个正方形而其他的都不会动。

  4. 对于步骤3的每个备选方案(每个备选方案都与规则1和2的移动结合),应仅对那些只能根据步骤3做出的决定移动的零件再次应用规则2。 / p>

有了这些“规则”,您就大大限制了要调查的州的数量,即列表的大小将受到更大的限制。唯一分支到替代路径的是规则3。

当然,要实现此目标需要付出一些努力。

其他优化

尽管不会提高时间复杂度,但是您可以通过使用高效的数据结构来获得执行时间的因素。

与其使用x,y坐标,不如使用一维位置标识,例如这样映射到6x6板上的位置标识:

 0  1  2  3  4  5
 8  9 10 11 12 13
16 17 18 19 20 21
24 25 26 27 28 29
32 33 34 35 36 37
40 41 42 43 44 45

此外,不要存储方向字母,而是存储相对于上述编号系统的相对位置变化:

Left = -1
Right = +1
Up = -8
Down = +8

因此,对于一个零件,您将具有两个数值属性:一个数字代表位置,另一个数字代表方向。

当结果位置不在上面列出的任何数字中时,棋盘上就会出现跑动。请注意,编号在行之间有间隙,因此也很容易检测到水平溢出。

此外,由于位置由一个数字而不是一对坐标组成,因此更容易,更快捷地测试两个零件是否位于同一位置。