如何通过删除不必要的步骤来改进此算法?

时间:2015-05-24 19:00:37

标签: algorithm foreach pseudocode

我有一个项目,它通过增加或减少其中一个值来组成一组数字。想象一下以下3x2网格:

1 1 1
2 2 2

我们只能将任意数字的值增加或减少2,这会使相邻(上,下,左和右)数字增加/减少1.例如,如果我们增加第一个数字的值,结果将是:

3 2 1 3 2 2

这样做的目的是找到在最少的步骤中使所有数字的值相等的方法。为了分析"移动"的所有可能组合,已经创建了一种算法,该算法经历从最低值(即0)到最高值的所有可能组合。在这种情况下,七(7)是最高值。算法在找到解决方案的那一刻停止。

然而,这导致程序浪费的分析步骤已经通过,例如,增加其值然后再次降低它,因为增加和减少是可以根据需要重复的步骤。下面的伪代码在每个单元的最大深度为7个值上需要18,853,802步,以找到解决方案。此外,有些单元可能是空的,因此产生更多无用的步骤,因为没有什么可以从它们读取。例如:

1 X 1
2 3 4

如何才能使算法跳过导致已经尝试过的状态的步骤?要求是它还可以返回用于查找答案的步骤,任何网格大小。

算法的伪代码如下:

function solve : x, y, direction, depth, currentSolution

//CurrentSolution is a copy
currentSolution.addTurn x, y, direction

//If move is not possible, return, all following turns are not necessary
if doTurn x, y, direction == false:
    return

depth++;

if maxDepth > MAX_DEPTH:
    return

if isSolved == true:
    solution.add(currentSolution)

foreach cell in gridCells:

    //If the previous turn was the same, just reversed, don't do anything
    if x != newX && y != newY && direction != Direction.DECREASE:
        //Do nothing
    else:
        solve newX, newY, Direction.INCREASE, depth

    if x != newX && y != newY && direction != Direction.INCREASE:
        //Do nothing
    else:
        solve newX, newY, Direction.DECREASE, depth

2 个答案:

答案 0 :(得分:1)

一种优化方法是将此问题视为图表中的shortest path problem

G=(V,E)是状态图,其中顶点是可能的状态:V = {all possible matrices},并且边是可能使用单个操作从一个状态移动到另一个状态:{{1 }}

现在,您可以在未加权的图表上使用最短路径算法。 BFS是一种可能的解决方案,与您的方法非常相似 - 但是由于BFS维护的E= { (u,v) | can change matrix u to v in one op}设置,保证您不会再次访问相同的状态两次。

另一种方法是使用A* Search Algorithm,使用一些启发式函数。

请注意:图表是符号的,您实际上不需要在开始之前计算它。您可以使用visited函数返回一组“下一个”顶点 - 可以在一步中从next(v)到达,然后使用此v函数模拟边缘,并在运行中仅创建所需图形的一部分。

答案 1 :(得分:1)

不要将此视为一组步骤,而应将其视为线性代数问题。操作通勤,因此唯一重要的是增加/减少每个节点的数量。

你有一个初始向量b。您希望在所有值相等的空间中生成向量。您可以添加或减去向量v1,v2,v3,...,vk。制作矩阵M,其列向量为v1,v2,...,vk。您想要找到系数a = {a1,a2,...,ak}的向量,以便M.a + b =常数向量。这是你可以使用线性代数解决的问题,但可以有0个解决方案或无限多个解决方案。

这是一个有0个解决方案的例子:

1  4  
2  6  

无论你做什么,总和的奇偶校验都会保持奇数,所以你不能使所有的值都相等。但它比这更糟糕。即使您允许分数移动,数字的交替总和(例如1-4 + 6-2)将保持不变,1,因此您无法到达具有相等数字和交替和0的位置。

由于以下移动模式产生0净变化,

+ -
- +

然后任何有解决方案的东西都有很多。此模式对应于零空间中的向量。

如果矩阵M在实数上是可逆的,那么你将得到每个最终向量的一个真实解。也许并非所有这些都可以通过整数步骤来达到。通常,当存在至少一个解时,存在一个解空间,并且您可以通过计算M的零空间和M a =全1矢量的解来找到该空间。您想在此子空间中找到最小L1范数的整数向量。也许有更好的解决方案,但您可以使用线性编程来解决这个问题。即使你采用一种低效,详尽的方法来搜索可能性,你也可以在比M的零空间大1的空间而不是n中做到这一点,我认为你会发现M的零空间是小。