Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/446.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:在(50000*50000网格)2d数组中寻路?_Javascript_Algorithm - Fatal编程技术网

Javascript:在(50000*50000网格)2d数组中寻路?

Javascript:在(50000*50000网格)2d数组中寻路?,javascript,algorithm,Javascript,Algorithm,问题 假设我们想象一个二维整数值数组,它代表一个网格地图,如下所示: +-----+------+-----+-----+-----+ | 10 | 2 | 2 | 4 | 656 | +-----+------+-----+-----+-----+ | 234 | 165 | 724 | 759 | 230 | +-----+------+-----+-----+-----+ | 843 | 734 | 999 | 143 | 213 | +-----+------+--

问题

假设我们想象一个二维整数值数组,它代表一个网格地图,如下所示:

+-----+------+-----+-----+-----+
| 10  |  2   |  2  |  4  | 656 |
+-----+------+-----+-----+-----+
| 234 | 165  | 724 | 759 | 230 |
+-----+------+-----+-----+-----+
| 843 | 734  | 999 | 143 | 213 |
+-----+------+-----+-----+-----+
| 242 | 2135 | 131 | 24  | 374 |
+-----+------+-----+-----+-----+
| 159 | 464  | 155 | 124 | 151 |
+-----+------+-----+-----+-----+

2d索引表示地图上某个单元的坐标,数组中的值表示穿越该单元地形的相对难度-例如999可能是厚荆棘,而2,3,4可能是略微倾斜的路径。。。或者别的什么

现在,我们想找到从网格上的[x,y]到网格上的[q,r]的最简单路径(换句话说,步骤之和是可能的最低值)

问题域

这需要在现代浏览器中运行,其中渲染了一个相当简朴的贴图,在用户输入[q,r]后,我们将通过所有中间顶点从[x,y]到[q,r]绘制一条线。很方便,[X,Y]总是相同的(为了简单起见,说[0,0])

所以使用Dijkstra算法或A*

所以我的第一反应是将数组建模为一个图,应用Dijkstra的算法,然后从那里开始工作。在上述情况下,使用5x5网格,效果良好。我遍历每个数组索引,并使用该值和相邻值生成一个节点,该节点的所有相邻节点都具有加权边。这就建立了一个图,我可以应用Dijkstra的算法

但是,在实践中,我将使用小于等于50000 x 50000的阵列!那是2.5亿

所以很明显,在运行Dijkstra算法时动态构建一个图是不适用的。我的下一个想法是预先计算路径(数据集是固定的),将它们存储在服务器上,并在得到目标[q,r]时进行回调……但这是250000000条路径。。。即使我让它在不到一秒钟的时间内运行(我认为不会),计算所有路径也需要几年时间


我想我可能需要采取另一种方法,但我不确定,我如何才能做到这一点

不要构造显式图(指针很昂贵)——使用坐标对表示队列中的节点,并修改Dijkstra实现以直接操作2d数组表示

使用类似于costs数组的数组来存储由算法计算的(最初是暂定的)距离

Dijkstra将在一次运行中计算所有节点的成本,因此,如果您的起点是固定的,那么只运行一次就足够了——无需运行数百万次

附言:在图像上创建了一个运行Dijkstra的JSFIDLE:

计算从鼠标单击到所有点的距离,其中较暗的像素被解释为更昂贵

对于较大的图像,速度会变慢,但到目前为止还没有设法使其崩溃,但我认为对于您的数据,浏览器中的内存将耗尽

Dijkstra实现使用以下接口来访问图形——我认为这应该是直接提供给数据结构顶部的,而无需显式生成内存中具有显式节点和边的“传统”图形数据结构:

/**
 * The interface the Dijkstra implementation below uses
 * to access the graph and to store the calculated final
 * and intermediate distance data.
 *
 * @Interface
 */
Graph = function() {};

/**
 * Returns the current distance for the given node.
 * @param {Object} node
 * @return {number}
 */
Graph.currentDistance = function(node) {};

/**
 * Stores the current distance for the given node.
 * @param {Object} node
 * @param {number} distance
 */
Graph.setCurrentDistance = function(node, distance) {};

/**
 * Returns an array of connected nodes for the given node, 
 * including the distances.
 *
 * @param {Object}
 * @return {Array<{cost:number, node:Object}>}
 */
Graph.connections = function(node) {};
/**
*下面Dijkstra实现使用的接口
*访问图表并存储计算的最终结果
*和中间距离数据。
*
*@接口
*/
图=函数(){};
/**
*返回给定节点的当前距离。
*@param{Object}节点
*@return{number}
*/
Graph.currentDistance=函数(节点){};
/**
*存储给定节点的当前距离。
*@param{Object}节点
*@param{number}距离
*/
Graph.setCurrentDistance=函数(节点,距离){};
/**
*返回给定节点的连接节点数组,
*包括距离。
*
*@param{Object}
*@return{Array}
*/
Graph.connections=函数(节点){};
p.p.S.:添加代码,以在第一次单击后的所有单击中显示短路路径。还修复了允许对角移动的错误:


总之,虽然这在浏览器中可能无法扩展到50k x 50x,但我认为这表明Dijkstra直接在阵列上运行是值得在服务器端尝试的,存储来自单个点的所有最短路径只需要一个与数据数组大小相同的数组。

您是如何将数组建模为图形的?您可能可以利用网格结构……查看本文:它是250 000 000,而不是250 000000@sopel你说得对,对不起!在我处理这个问题的过程中,作用域已经改变了几次。@StefanHaustein我很天真地生成了这个图。我只是遍历数组,为每个索引创建一个图,然后根据相邻索引的难度生成边的权重…有意义吗?