从A [a,b]到A [c,d]的不同非循环路径的数量?

时间:2010-03-23 14:56:35

标签: c++ algorithm math graph-theory discrete-mathematics

我正在写一个sokoban解算器,用于娱乐和练习,它使用一种简单的算法(类似于BFS,但有点不同)。

现在我想估计它的运行时间(O和omega)。但需要知道如何计算网络中从顶点到另一个的非循环路径的计数。 实际上,我想要一个表达式来计算m * n顶点矩阵的两个顶点之间的有效路径计数。

有效路径:

  • 访问每个顶点0或一次。
  • 没有电路

例如,这是一个有效的路径:

alt text http://megapic.ir/images/f1hgyp5yxcu8887kfvkr.png

但这不是:

alt text http://megapic.ir/images/wnnif13ir5gaqwvnwk9d.png

我们需要一种方法来查找两个顶点 a b 之间所有非循环路径的计数。

欢迎对解决方法和技巧的评论。

5 个答案:

答案 0 :(得分:4)

计算图表中简单路径数量的一般问题是#P完成。一些#P完全问题具有完全多项式随机化近似方案,有些则没有,但您声称对近似不感兴趣。也许有一种方法可以利用网格结构,就像计算Tutte多项式一样,但我对如何做到这一点没有任何想法。

答案 1 :(得分:4)

不是解决方案,但也许你可以进一步思考这个想法。问题是你还需要计算获得所有路径的最长路径。对于一般图形,longest path problem是NP完全的,因此即使对于相对较小的图形(8x8和更大),它也会花费很长时间。

想象一下,起始顶点位于顶部,左上角,末端顶点位于矩阵的右下角。

  • 对于1x2矩阵,只有一条可能的路径
  • 2x2矩阵=> 2 *** 1 **路径=> 2
  • 3x2矩阵=> 2 *** 2 **路径=> 4
  • 3x3矩阵=> 2 *** 4 ** + 2 * 2路径=> 12
  • 3x4矩阵=> 2 *** 12 ** + 12 + 2路径=> 38

每次我将前一次计算的结果与当前路径数相结合。对于这样的平面图可能有一个非常接近的公式,也许甚至有很多理论,但我太愚蠢......

您可以使用以下Java(抱歉,我不是c ++专家: - /)片段来计算更大矩阵的可能路径:

public static void main(String[] args) {
    new Main(3, 2).start();
}
int xSize;
int ySize;
boolean visited[][];

public Main(int maxX, int maxY) {
    xSize = maxX;
    ySize = maxY;
    visited = new boolean[xSize][ySize];
}

public void start() {
    // path starts in the top left corner
    int paths = nextCell(0, 0);
    System.out.println(paths);
}

public int nextCell(int x, int y) {
    // path should end in the lower right corner
    if (x == xSize - 1 && y == ySize - 1)
        return 1;

    if (x < 0 || y < 0 || x >= xSize || y >= ySize || visited[x][y]) {
        return 0;
    }

    visited[x][y] = true;
    int c = 0;
    c += nextCell(x + 1, y);
    c += nextCell(x - 1, y);
    c += nextCell(x, y + 1);
    c += nextCell(x, y - 1);
    visited[x][y] = false;
    return c;
}

=&GT;

  • 4x4 =&gt; 184
  • 5x5 =&gt; 8512
  • 6x6 =&gt; 1262816
  • 7x7(即使这个简单的案例需要花费很多时间!)=&gt; 575780564

这意味着您可以(仅在理论上)计算从MxM矩阵的任何位置到右下角的所有可能路径,然后使用此矩阵快速查找路径数。 Dynamic programming(使用之前的计算结果)可能会加快一些速度。

答案 2 :(得分:3)

项目Euler上存在类似但不太普遍的问题:http://projecteuler.net/index.php?section=problems&id=237

我认为论坛中描述的一些解决方案可以扩展到解决您的一般情况。这是一个相当困难的问题,特别是对于你的一般情况。

要访问他们的论坛,首先需要解决问题。我不会在这里发布答案,也不会链接到列出答案的某个网站,这个网站可以通过搜索非常明显的内容在Google上轻松找到。

答案 3 :(得分:2)

这是数学中的一个开放性问题,直接应用于化学和物理学,用于模拟聚合物键。最早的一些工作是在曼哈顿计划(核弹二战)期间完成的。

更为人所知的是自我避免行走问题。

我在我的大学数学系度过了一个夏天,研究了一种称为枢轴算法的蒙特卡罗算法,以近似给定长度n的自躲避步行数量的渐近拟合的参数。

请参阅Gordon Slade的优秀书籍“The Self Avoiding Walk”,以便广泛报道迄今为止用于解决此问题的各种技术。

这是一个非常复杂的问题,我想知道你的动机是什么。也许你可以找到一个更简单的模型,因为Self Avoiding Walks并不简单。

答案 4 :(得分:1)

显示边缘的矩阵是否有效?考虑构建一个显示边缘位置的矩阵,即。 [a,b] = 1&lt; =&gt; a-> b是图中的边,否则为0。现在,将此矩阵提升为各种幂,以显示使用n个步骤在顶点之间存在多少种方法,然后将它们相加以得到结果。这只是解决问题的一种方法,可能还有其他方法来解决问题。

我想知道这是否属于MathOverflow,作为另一个想法


是的,一旦你有一个零矩阵你就可以在你的情况下停止取幂,3之后没有很多地方可去,但从1到3的路径将是直接的和经过的路径2,所以在找到全零之前,只有几个矩阵可以加在一起。


我认为应该有一种方法来计算n ^(n + 1)的界限,其中n是图中顶点的数量,它表示一个停止点,就像那个点,每个顶点将被访问过一次。我不确定如何从循环路径中解决问题,或者可以假设图形没有循环?