Javascript 5x5网格中所有可能的移动?

Javascript 5x5网格中所有可能的移动?,javascript,arrays,algorithm,function,formula,Javascript,Arrays,Algorithm,Function,Formula,我如何计算一个人从s到e的所有可能路径,而不使用同一个正方形两次 我已经创建了一个网格阵列[[1,1]…[5,5]],但我不知道这是否可行 我还绘制了可能的方块图,并试图创建一个记录、检查和许多垃圾 我可以在这里使用任何标准公式吗?您可以使用带回溯的深度优先搜索来查找所有可能的路径。这个想法很简单,从S开始,访问S的任何邻居,然后从该邻居访问任何其他邻居,同时在回溯移除顶点的“已使用”状态后,将该顶点标记为“已使用”,以便在其他路径中重用它,等等。。。。一旦到达E,您将增加路径数。路径必须受到限

我如何计算一个人从
s
e
的所有可能路径,而不使用同一个正方形两次

我已经创建了一个网格阵列[[1,1]…[5,5]],但我不知道这是否可行

我还绘制了可能的方块图,并试图创建一个记录、检查和许多垃圾


我可以在这里使用任何标准公式吗?

您可以使用带回溯的深度优先搜索来查找所有可能的路径。这个想法很简单,从S开始,访问S的任何邻居,然后从该邻居访问任何其他邻居,同时在回溯移除顶点的“已使用”状态后,将该顶点标记为“已使用”,以便在其他路径中重用它,等等。。。。一旦到达E,您将增加路径数。路径必须受到限制,所以我假设你指的是不多次使用一个顶点的路径,或者你可以有无限个循环


Frank提到了加泰罗尼亚数字,这确实有效,但只适用于单调路径,即只有右/下或左/上的路径。此外,DP不起作用,因为这是一个NP难问题(非多项式时间来找到解决方案并进行验证,因为基本上需要再次找到所有路径以确保它们匹配)。

有很多标准的路径查找算法可用于此

这与javascript无关

您可以使用一个算法节奏而不使用启发式,并且您不应该停止在第一个解决方案上

以下是您如何做到这一点:

诀窍是你需要将已经访问过的方块存储在一个列表中,并检查你是否在每一步都重新访问其中一个方块

另一个技巧是你需要在相邻的方块之间有明确的顺序。(比如上/右/下/左。这是一个非常愚蠢的算法节奏,但对于这种特殊情况来说很好。)

您还需要能够识别正方形(可以通过其位置进行识别)

考虑一个递归函数(例如,将其命名为Visit):

通过访问(开始)启动此算法。您将在goallist中获得结果,goallist是一个路径列表

另外,它只有半个javascript半个伪代码,但很容易用它编写javascript

编辑:享受解决方案:

function visit(square) {

    add the square to the pathlist //pathlist is not a list of paths but a list of squares which is the current path

    if (square is the goal) {
        add a copy of the pathlist to the goalslist
    }
    else {
        for (each adjacency in square.adjacencies) { // this can be calculated by adding +1 and -1 to the coordinates, and checking if its overflowing (less then one/more than five)
            if (adjacency is in pathlist) {
                //do nothing we have already been here
            }
            else {
                visit(adjacency)
            }
        }
    }

    remove square from the pathlist!!
}

var start=[1,1],
目标=[5,5],
路径列表=[],
solutionList=[],
solutionCount=0,
宽度=5,
高度=5;
函数squareInArray(正方形,数组){
var i=0,
x=平方[0],
y=平方[1];
对于(i=0;i宽度| |邻接[i][1]<1 | |邻接[i][1]>高度){
//溢出
}
否则{
if(squareInArray(邻接[i],路径列表)){
//什么都不做我们已经来过这里了
}
否则{
访问(邻接[i]);
}
}
}
}
pathList.pop();
}
访问(开始);
警报(解决方案计数);
8512个目标。还有人应该检查我的代码是否正确


查看这把小提琴:

有关这个问题的参考文献和参考书目,以及一个循环关系,请参阅韦斯坦的《数学世界》。非常不幸的是,我找不到雅培和汉森讨论这个问题的文章

正方形大小的序列的增长速度是惊人的。据了解,在12×12的正方形中,自避步行的数量是1824132915142480494241470885236,一个30位数字

谢谢你的提问,这确实是一个深刻而发人深省的问题


编辑:如果允许对角线步骤,则数字增长得更快。这是OEIS序列,由于D.Knuth。即使是一个5×5的正方形(超过4亿条路径),也很难使用暴力。有一种称为ZDD的技术,他用来计算这些数字。

2乘以你的平方有多大。在你的情况下,2到电源od 5是32。因此有三十二条不同的可能路线。可以使用以下示例来证明这种模式。0x0的正方形虽然不可能,但从技术上讲,它有一种从A到B的可能方式,因为它已经存在了。1x1的正方形有两条可能的路径(如果你不相信我,请画出来并找出答案。这个模式非常明显,甚至与帕斯卡三角形有关。希望我能帮上忙。

如果你在5x5网格中工作,有一个简单的数学解决方案。在网格的底部和顶部写1,并添加角点,直到你到达终点,最后角点的数字就是路径数。这是假设你只能左右移动

以下是一个例子:

11 1 o o o 1 2 3 4 5 6 1 o o o o--1 3 6 10 15 21 1 o o o o---1 4 10 20 35 56 1 o o o 1 5 15 35 70 126 1 o o o 1 6 21 56 126 252

所以答案是252

您也可以使用阶乘公式是(每个右侧和下方的网格数)!除以(左侧)!除以(下方)!=路径数

所以你的方程看起来像是10除以5除以5=252


记住,只有当一个人只能向下和向左走时,这才有效!

你说的“不使用同一个正方形两次”是什么意思?请详细说明。只是说在你的道路上,你永远不会经过同一个正方形a
function visit(square) {

    add the square to the pathlist //pathlist is not a list of paths but a list of squares which is the current path

    if (square is the goal) {
        add a copy of the pathlist to the goalslist
    }
    else {
        for (each adjacency in square.adjacencies) { // this can be calculated by adding +1 and -1 to the coordinates, and checking if its overflowing (less then one/more than five)
            if (adjacency is in pathlist) {
                //do nothing we have already been here
            }
            else {
                visit(adjacency)
            }
        }
    }

    remove square from the pathlist!!
}
<script type="text/javascript">
var start = [1,1],
    goal = [5,5],
    pathList = [],
    solutionList = [],
    solutionCount = 0,
    width = 5,
    height = 5;


function squareInArray(square, array) {
    var i = 0,
        x = square[0], 
        y = square[1];

    for (i = 0; i < array.length; i++) {
        if (x == array[i][0] && y == array[i][1]) {
            return true;
        }
    }
    return false;
}


function visit(square) {
    var i = 0,
        x = square[0], 
        y = square[1],
        adjacencies = [[x-1,y],[x+1,y],[x,y+1],[x,y-1]];

    pathList.push(square);

    if (x == goal[0] && y == goal[1]) {
        var solution = pathList.slice(0); //copy trick
        solutionList.push(solution);
        solutionCount++;
        //alert(solution);
    }
    else {
        for (i = 0; i < adjacencies.length; i++) {
            if (adjacencies[i][0] < 1 || adjacencies[i][0] > width || adjacencies[i][1] < 1 ||adjacencies[i][1] > height) {
                //overflow
            }
            else {
                if (squareInArray(adjacencies[i], pathList)) {
                    //do nothing we have already been here
                }
                else {
                    visit(adjacencies[i]);
                }
            }
        }
    }

    pathList.pop();
}

visit(start);

alert(solutionCount);
</script>