首先,这是我们去年在一个项目中必须解决的四个问题之一,我找不到合适的算法,所以我们处理暴力解决方案。
问题:这些数字位于未排序的列表中,仅支持一种操作。该操作定义如下:
给定位置i和位置j,操作将位置i处的数字移动到位置j而不改变其他数字的相对顺序。如果我&gt; j,位置j和i-1之间的数字的位置增加1,否则如果i <1。 j位置i + 1和j之间的数字位置减少1.此操作需要i步骤找到要移动的数字,j步骤找到要移动它的位置。然后,将多个位置i移动到位置j所需的步数是i + j。
我们需要设计一个给出数字列表的算法,确定重新排列序列的最佳(按成本计算)移动顺序。
尝试: 我们的部分调查是围绕NP完全性,我们将其作为一个决策问题,并尝试找到适当的转换,以解决Garey和Johnson的书中列出的任何问题:计算机和难以处理,没有结果。在唐纳德·E·克努特(Donald E. Knuth)的着作“计算机编程艺术”中,也没有直接参考(从我们的观点来看)这种变化。 3排序和搜索。我们还分析了对链接列表进行排序的算法,但没有一个能够找到最佳的运动序列。
请注意,这个想法不是找到一个对序列进行排序的算法,而是要告诉我组织序列的成本方面的最佳运动顺序,你可以复制并对其进行排序以分析最终位置如果你想要的元素,事实上我们可以假设列表包含从1到n的数字,所以我们知道我们想要把每个数字放在哪里,我们只关心最小化步骤的总成本。
我们测试了几种贪婪的方法,但它们都失败了,分而治之的排序算法无法使用,因为它们与列表中没有成本部分交换,我们的动态编程方法必须考虑很多情况。
蛮力递归算法采用从i到j的所有可能的移动组合,然后是元素其余部分的所有可能时刻,最后它返回序列的总成本较少的序列,如你可以想象这个算法的成本是残酷的,并且超过8个元素是不可行的。
我们的观察结果:
n移动不一定比n + 1移动便宜(与O(1)数组中的交换不同。)
基本上有两种方法可以将一个元素从位置i移动到j:一个是直接移动它,另一个是以其到达位置j的方式移动i周围的其他元素。
最多你进行n-1次动作(未触动的元素单独到达其位置)。
如果它是最佳的动作序列,那么你不会移动相同的元素两次。
答案 0 :(得分:2)
这个问题似乎是approximation algorithm的一个很好的候选人,但这只会给我们一个足够好的答案。既然你想要最佳答案,那就是我要采取的改进蛮力方法的方法。
我不是盲目地尝试每一种排列,而是使用backtracking方法来维持找到的最佳解决方案,并修剪任何超出我们最佳解决方案成本的分支。我还要添加一个transposition table,以避免重新搜索前一个分支使用不同移动排列所达到的状态。
我还会添加一些启发式方法来探索在任何其他动作之前更有可能达到良好结果的动作。例如,首先选择成本较低的移动。我需要先进行实验,然后才知道哪种启发式方法最有效。
我还会尝试在原始数组中找到longest increasing subsequence of numbers。这将为我们提供一系列不需要移动的数字,这些数字应该大大减少我们需要探索的分支数量。这也大大加快了几乎排序的列表上的搜索速度。
我希望这些改进能够处理远大于8的列表,但在处理大量随机数时,我更喜欢近似算法。
根据大众需求(1人),这就是我用genetic algorithm(我最熟悉的元经济学)解决这个问题的方法。
首先,我首先计算数字的最长增长子序列(见上文)。必须移动不属于该组的每个项目。我们现在需要知道的只是按照什么顺序。
用作遗传算法输入的基因组只是一个数组,其中每个元素代表一个要移动的项目。项目在数组中显示的顺序表示它们必须移动的顺序。适应度函数将是原始问题中描述的成本计算。
我们现在拥有将问题插入标准遗传算法所需的所有元素。其余的只是调整。很多很多调整。