2016-02-01 62 views
3

我有一个常规网络N节点连接在一起,我想要生成一个路径,访问n节点只有一次。我还要求路径中存在某种程度的随机性,以便能够在给定相同的起始节点的情况下创建不同的路径。如何通过网络中的节点生成随机路径

See the problem illustration here.

我当前的解决方案是选择一个随机开始节点然后随机访问相邻节点,并重复直到我访问Ñ节点。无论何时该路径不允许我访问节点,我都会回溯尝试通过另一个节点。

当节点和连接的数量小,这个工作得很好,但是当这些增加和ñ接近ň需要花费很长的,如果在所有寻找解决办法。

您能否建议保证在合理时间内成功的替代方法?

+1

Prim的算法和其他设计用于查找[最小生成树](https://en.wikipedia.org/wiki/Minimum_spanning_tree) –

+0

想找到'解决方案'或'全部'解决方案吗? – Aravind

+0

@Aravind一个解决方案就足够了 – mpium

回答

3

而不是试图创建一个独特的路径,这将导致你失望许多死胡同,你可以创建单路径作为分支路径的轮廓。这些路径将具有相邻的起点和终点。

这个数字概括了该算法的步骤:

Four steps of the proposed algorithm

首先,划分网格的一半(一)。如果其中一个维度很奇怪,请忽略最后一行或一列。

现在在粗网格(b)上创建一个分支连接的迷宫。有很多算法, Prim的算法在评论中被提及,但是如果你没有回溯,你也可以使用你的贪婪路径搜索。 Mike Bostock的Visualizing Algorithms展示了一些迷宫生成算法;他们接近长页面的底部。

接下来,创建该迷宫的轮廓。这给你一个简单的路径,如果它的尺寸甚至是(c),就访问原始网格中的所有节点。起点和终点将相邻;路径仅仅是被关闭了一步。

如果原始网格的任何维度都是奇数,则可以拉伸随机行或列以覆盖整个网格(d)。请注意,您必须为每个交点行或列插入一个新段。否则,一些节点将不会被访问。 (当两个尺寸都是奇数并且必须进行调整时可能存在问题,所以这是算法的另一个限制:最多一个维度可以是奇数。)

编辑:概念验证实现(无步骤d)在Javascript下面。这是一个完整的网页,您可以将其保存为html文件并显示在识别canvas元素的浏览器中。

<!DOCTYPE html> 

<html> 

<head> 
<meta charset="utf-8" /> 
<title>Simple Path Demo</title> 
<script type="text/javascript"> 

    function array2d(w, h, val) { 
     var arr = []; 

     for (var y = 0; y < h; y++) { 
      var row = []; 

      for (var x = 0; x < w; x++) row.push(val); 
      arr.push(row); 
     } 

     return arr; 
    } 

    var dir = { 
     n: {x: 0, y: -1}, 
     e: {x: 1, y: 0}, 
     s: {x: 0, y: 1}, 
     w: {x: -1, y: 0}, 
    }; 

    var width = 72; 
    var height = 72; 

    var node = array2d(width, height, false); 



    function walk(x, y, from) { 
     if (x < 0 || x >= width/2) return; 
     if (y < 0 || y >= height/2) return; 

     if (node[2*y][2*x]) return; 

     node[2*y][2*x] = true;   

     if (from == 'n') node[2*y + 1][2*x] = true; 
     if (from == 'e') node[2*y][2*x - 1] = true; 
     if (from == 's') node[2*y - 1][2*x] = true; 
     if (from == 'w') node[2*y][2*x + 1] = true; 

     var d = ['n', 'e', 's', 'w']; 

     while (d.length) { 
      var pick = (Math.random() * d.length) | 0; 
      var head = d[pick]; 
      var next = dir[head]; 

      d[pick] = d[d.length - 1]; 
      d.pop(); 

      walk(x + next.x, y + next.y, head); 
     }   
    } 

    function cell(x, y) { 
     if (y < 0 || y >= height) return false; 
     if (x < 0 || x >= width) return false; 

     return node[y][x]; 
    } 

    function path(x, y) { 
     var x0 = x; 
     var y0 = y; 

     var res = ""; 
     var dir = "s"; 

     var l, r; 

     y++; 

     while (x != x0 || y != y0) { 
      var old = dir; 

      res += dir; 

      switch (dir) { 
      case "n": l = (cell(x - 1, y - 1)) ? 1 : 0; 
         r = (cell(x, y - 1)) ? 2 : 0; 
         dir = ["w", "n", "e", "e"][l + r]; 
         break; 

      case "e": l = (cell(x, y - 1)) ? 1 : 0; 
         r = (cell(x, y)) ? 2 : 0; 
         dir = ["n", "e", "s", "s"][l + r]; 
         break; 

      case "s": l = (cell(x, y)) ? 1 : 0; 
         r = (cell(x - 1, y)) ? 2 : 0; 
         dir = ["e", "s", "w", "w"][l + r]; 
         break; 

      case "w": l = (cell(x - 1, y)) ? 1 : 0; 
         r = (cell(x - 1, y - 1)) ? 2 : 0; 
         dir = ["s", "w", "n", "n"][l + r]; 
         break; 
      } 

      if (dir == "n") y--; 
      if (dir == "e") x++; 
      if (dir == "s") y++; 
      if (dir == "w") x--; 
     } 

     return res; 
    } 

    walk(0, 0); 
    var p = path(0, 0); 

    window.onload = function() { 
     var cv = document.getElementById("map"); 
     var cx = cv.getContext("2d"); 
     var s = 8; 

     cx.translate(2*s, 2*s); 
     cx.lineWidth = 2; 

     var x = 0; 
     var y = 0; 

     cx.beginPath(); 
     cx.moveTo(s*x, s*y); 

     for (var i = 0; i < p.length; i++) { 
      var c = p.charAt(i); 

      x += dir[c].x; 
      y += dir[c].y; 

      cx.lineTo(s*x, s*y); 
     } 

     cx.stroke(); 
    } 

</script> 
</head> 

<body> 
<canvas id="map" width="608" height="608">Kann nix.</canvas> 
</body> 

</html> 
0

至于评论,我不知道,你可以找到的东西比你已经有一个无向图中未加权做快。

确保您正在实施Depth-First(或Breadth-first)搜索算法的正确版本并添加您的随机选择的相邻节点。

另一种贪婪的解决方法是随机为每个顶点定义一个权重并应用Dijkstra's algorithm