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

Posted

技术标签:

【中文标题】从 A[a,b] 到 A[c,d] 的不同非循环路径的计数?【英文标题】:count of distinct acyclic paths from A[a,b] to A[c,d]? 【发布时间】:2010-03-23 14:56:35 【问题描述】:

我正在写一个推箱子求解器来娱乐和练习,它使用一个简单的算法(有点像 BFS 有点不同)。

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

有效路径:

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

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

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

但这不是:

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

需要一种方法来计算两个顶点ab 之间的所有非循环路径的计数。

欢迎大家学习解决方法和技巧。

【问题讨论】:

可能路径的数量将比 BFS 考虑的路径数量大很多,所以我看不出它有什么帮助。 BFS 反复将相似的路径组合在一起,从而降低了复杂性。 BFS 的复杂度为 O(|V|+|E|)。 您想要所有路径的列表还是仅路径数?如果你想要路径的数量,你会接受一个近似值吗? 我不想列出它们。我想计算它们的数量而不计算它们。 没有。但如果您对此有任何想法,请与我们分享? 只是想知道,为什么这个社区维基而不是一个普通的问题? 【参考方案1】:

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

假设起始顶点在矩阵的左上角,结束顶点在矩阵的右下角。

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

每次我结合当前路径数的先前计算的结果。可能是这样的平面图有一个接近的公式,甚至可能有很多理论,但我太愚蠢了......

您可以使用以下 Java(对不起,我不是 c++ 专家:-/)sn-p 来计算更大矩阵的可能路径:

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;

=>

4x4 => 184 5x5 => 8512 6x6 => 1262816 7x7(即使是这个简单的案例也需要很多时间!)=> 575780564

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

【讨论】:

感谢您提供有用的建议和解决方案。 我很高兴它有帮助,我希望这是有道理的并且几乎没有错误。感谢这个有趣的问题:-)! 在此处查看第一个参考资料(blum + hewitt:二维磁带上的自动机):ftp.inf.fu-berlin.de/pub/reports/tr-b-97-08.ps.gz -> 他们在那里计算 KxK 网格中可能的循环数。也许这与您的问题几乎相同->只需将右下角顶点与左上角顶点连接即可? 对 OEIS 的搜索显示 NxN 的前 19 个值是已知的:research.att.com/~njas/sequences/… (只有 19 个非常强烈地表明文献中没有封闭式公式。)【参考方案2】:

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

【讨论】:

我很确定路径的数量是有限的。我不确定,但我认为计数必须有一个递归序列,如果没有实际评估,也很难估计它。 实际上,近似比精确计算要容易得多。如果您改变主意,请编辑问题... “如果不进行实际评估,将很难估计它”-> 是的,这正是我的想法。您可以查找平面图的理论以获得近似公式:cs.brown.edu/sites/jgaa/accepted/2007/…【参考方案3】:

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

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

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

【讨论】:

亲爱的 IVlad,我认为这比您所说的问题更普遍。因为第 237 题的第 3 条规则说:游览恰好访问每个广场一次。但这里的游览参观每个广场不到两次。 (1 或 0 次)并且游览在 2 个任意且不同的顶点之间开始和结束。【参考方案4】:

这是数学中的一个开放式问题,直接应用于化学和物理,以使用它来模拟聚合物键。最早在这方面所做的一些工作是在曼哈顿项目(二战核弹)期间完成的。

更广为人知的是自我避免步行问题。

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

请参阅 Gordon Slade 的名为“The Self Avoiding Walk”的优秀书籍,了解迄今为止用于解决此问题的技术类型的广泛介绍。

这是一个非常复杂的问题,我想知道您考虑它的动机是什么。也许您可以找到一个更简单的模型来满足您的需求,因为自我避免步行一点也不简单。

【讨论】:

【参考方案5】:

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

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


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


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

【讨论】:

考虑 1 -> 2, 1 -> 3, 2 -> 3. 邻接矩阵:0 1 1 | 0 0 1 | 0 0 0。这个矩阵的元素通过重复取幂最终都为零。如果您考虑一个对称邻接矩阵(对于无向图),那么您怎么知道何时停止求幂? 如果矩阵永远不会变成 0 会发生什么?你怎么知道什么时候停下来? 所描述的方法还将计算一些节点被多次访问的路径,所以这充其量是路径数量的上限。该矩阵不保留有关已访问节点的信息,仅保留从 a 到 b 的路径数。

以上是关于从 A[a,b] 到 A[c,d] 的不同非循环路径的计数?的主要内容,如果未能解决你的问题,请参考以下文章

Educational CF # 17 C 二分,字符串 D 最长路,dp

3路/4路循环赛调度算法

csharp 当(a + b)=(c + d)时,使用嵌套for循环打印“幸运数字”的示例。从计算机编程基础与C#http:// www

csharp 当(a + b)=(c + d)时,使用嵌套for循环打印“幸运数字”的示例。从计算机编程基础与C#http:// www

汉诺塔的非递归实现(栈)

分支循环语句