我有什么算法或方法可以解决寻找从A点到B点的路径的特定问题,其中两个点不在同一平面上(在化合物的不同楼层/水平上) - 可能不在同一栋楼里。)
我正在考虑A*和Dijkstra's算法。然而,基于这个算法只有这个(如果我错了,纠正我)只关注一个地图。具有不同的地图(由于许多楼层和许多建筑物)可以对于所述算法具有不同的故事。
根据难度,我为所有地图设计了一种格式,以跟踪数据的一致性。在每个地图中,存在建筑物名称,楼层编号和每个楼层可能具有的楼层以及楼层平面图(转换为二维单个字符阵列)的数据。例如(两个地图都在不同的文件上):
//MainFloor1 //MainFloor2
Main Main
1st 2nd
1:Wall 1:Wall
2:Door 2:Door
3:Elevator 3:Elevator
# 4:Room1
1111441111 5:Room2
1 1 #
1 1 1111441111
1 1 1552 2441
1111221111 1551 1441
# 1551 1441
//End-MainFloor1 1111221111
#
//End-MainFloor2
如果我想考虑从A点(从MainFloor1的第一个'2'以下)到B点(MainFloor2左上角的第一个'4'),我会从给定的地图中返回结果
// X is the path from Point A to Point B
1111X41111 1111X41111
1 X 1 1552XXXB41
1 X 1 1551 1441
1 X 1 1551 1441
1111A21111 1111221111
我会考虑或采取什么方法从给定的地图输入中产生这样的结果?
由于
答案 0 :(得分:2)
// X is the path from Point A to Point B
1111B11111
1 X 1
1 X 1
1 X 1
1111A11111
这是一个仅适用于单层的解决方案,
机器人只能在4个方向上移动..
建议的解决方案是使用禁忌列表进行BFS(广度优先搜索)
使用这些课程:https://stackoverflow.com/a/15549604/2128327
class Floor
{
public ArrayList<Point> points;
public int minX, minY, maxX, maxY;
public Floor ()
{
p = new ArrayList<Point>();
}
}
单层解决方案:
class PathFinder
{
public static Floor floor;
public static Point location;
public static void search (Floor floor, Point dest, Point initial_location)
{
QueueSet<Point> fringe = new QueueSet<Point>();
ArrayList<Point> taboo = new ArrayList<Point>();
boolean solution_found = false;
Point p = null;
fringe.enqueue(initial_location);
while (fringe.size() > 0)
{
p = fringe.dequeue();
taboo.add(p);
if (p.x == dest.x && p.y == dest.y)
{
solution_found = true;
break;
}
if (p.x > floor.minX && !taboo.contains(new Point(p.x-1,p.y))
fringe.enqueue(new Point(p.x-1,p.y));
if (p.x < floor.maxX && !taboo.contains(new Point(p.x+1,p.y))
fringe.enqueue(new Point(p.x+1,p.y));
if (p.y > floor.minY && !taboo.contains(new Point(p.x,p.y-1))
fringe.enqueue(new Point(p.x,p.y-1));
if (p.y < floor.maxY && !taboo.contains(new Point(p.x,p.y+1))
fringe.enqueue(new Point(p.x,p.y+1));
}
// taboo list represent the path taken so far
fringe.clear();
}
}
答案 1 :(得分:2)
A *,BFS和其他都是适用于graphs的算法。您的问题可以被认为是两个节点(顶点)之间存在边缘的图形(如果它们相邻且位于同一层,或,如果它们代表相同的电梯但是在不同的楼层。
请注意,您可以在内存中显式构建图形,但您不必这样做 - 您可以从路径查找器的角度将其视为一个。
答案 2 :(得分:0)
根据您的实施情况,应该可以将一个图表中的多个地图与特定点的互连结合起来。我认为这是BlueRaja一直试图解释的想法。
A *算法(以及Djkstra)基于查询离开图的节点的边以及它们各自的权重。在大多数语言中,此图形对象可以抽象为opaque类型和一组操作来查询其内容:例如,在Java中,操作集将构成一个接口,而实现接口的类的opaque类型将被反转回来到那个界面。其他语言可能以不同的方式提供这种机制,例如在具有结构,签名和仿函数的ML方言中。
如果算法是围绕这个接口构建的,那么应该很容易用另一种类型来替换实现图形界面的楼层地图类,其内容将是几个楼层地图,以及在内部传递均匀规则边缘的必要函数或方法地板和地板之间的特殊边缘。有了这个新的建筑类,人们可以想象封装(遵循相同的模式)几个建筑物实例,使用特殊代码将建筑物内部和外部连接作为图形边缘。
如果抽象得很好,A *算法实现应该与图形,节点和边缘的实现细节完全正交,并且它应该能够与支持图形界面的任何对象一起执行。
例如,这是Graph的可能接口:
interface Graph<Node, Scalar> {
int compare(Node n1, Node n2);
Collection<Node> getNeighbourgs(Node n);
Scalar getCost(Node n1, Node n2);
}
其中Node
是图中的节点,Scalar
表示节点之间的成本(或距离)的类型。
class Cell<Position extends Comparable<Position>> implements Comparable<Cell<Position>> {
private Position position;
public Cell(Position p){
position = p;
}
Position getPosition(){
return position;
}
int compareTo(Cell<Position> c){
return position.compareTo(c.getPosition());
}
}
abstract class WorldCell extends Cell<Position> {
public WorldCell(Position p){
super(p);
}
}
abstract class World implements Graph<WorldCell, Integer> {
private Building [] buildings;
private HashMap<WorldCell, LinkedList<WorldCell>> gateways;
int compare(WorldCell n1, WorldCell n2){
return n1.compareTo(n2);
}
public Collection<WorldCell> getNeighbourgs(WorldCell c){
// build the collections of cells from the building it belongs to
// and the gateways (connections between buildings
}
Scalar getCost(Node n1, Node n2){
// compute the cost based on the node positions in space
}
}
abstract class Building implements Graph<WorldCell, Integer> {
private Floor [] floors;
private HashMap<WorldCell, LinkedList<WorldCell>> gateways;
int compare(WorldCell n1, WorldCell n2){
return n1.compareTo(n2);
}
public Collection<WorldCell> getNeighbourgs(WorldCell c){
// build the collections of cells from the floor it belongs to
// and the gateways (connections between floors)
}
此部分类集提供了Graph
的多个实现的初始草图。 Floor
类将使用World
类实例数组复制与Building
或Room
中相同的代码。
当然,我们可以在这里看到像容器这样的“俄罗斯娃娃”的模式,这当然可以以某种方式抽象出来,但这个例子的目的是展示如何通过世界不同的地方实现相同的界面意图建模。