Algorithm 编程理论:解迷宫
解决迷宫的可能方法有哪些?Algorithm 编程理论:解迷宫,algorithm,maze,Algorithm,Maze,解决迷宫的可能方法有哪些? 我有两个想法,但我认为它们不太优雅 基本情况:我们有一个矩阵,这个矩阵中的元素以一种表示迷宫的方式排列,一个是进,一个是出 我的第一个想法是送一个机器人穿过迷宫,跟随一边,直到它走出迷宫。我认为这是一个非常缓慢的解决方案 第二个路径通过每个标有1的连续项目,检查它可以到达的位置(上、右、下、左)选择一条路径并继续其路径。这比第一个还要慢 当然,如果我让两个机器人在每个连接点都多线程,速度会快一点,但这也不是最好的方法 需要有更好的解决方案让机器人通过迷宫 编辑 第一:
我有两个想法,但我认为它们不太优雅 基本情况:我们有一个矩阵,这个矩阵中的元素以一种表示迷宫的方式排列,一个是进,一个是出 我的第一个想法是送一个机器人穿过迷宫,跟随一边,直到它走出迷宫。我认为这是一个非常缓慢的解决方案 第二个路径通过每个标有1的连续项目,检查它可以到达的位置(上、右、下、左)选择一条路径并继续其路径。这比第一个还要慢 当然,如果我让两个机器人在每个连接点都多线程,速度会快一点,但这也不是最好的方法 需要有更好的解决方案让机器人通过迷宫 编辑
第一:谢谢你的回答 我问题的第二部分是:如果我们有一个多维图,该怎么办?是否有专门的实践,或者贾斯汀L.的答案也适用于此?
我认为这不是解决这个问题的最好办法 第三个问题:
以下哪种迷宫求解算法最快?(完全假设)用矩阵构建一个图形,使用广度优先搜索、深度优先搜索或Dijkstras算法怎么样?有很多迷宫求解算法:
对于机器人来说,它看起来很有前途。你可以把迷宫想象成一棵树 A / \ / \ B C / \ / \ D E F G / \ \ H I J / \ L M / \ ** O (which could possibly represent) START + +---+---+ | A C G | +---+ + + + | D B | F | J | +---+---+ +---+---+ | L H E I | +---+ +---+---+ | M O | + +---+ FINISH (ignoring left-right ordering on the tree) 请注意,当迷宫中有“循环”时,这种方法只会变得稍微复杂一点(即,如果没有回溯,您可以重新进入已经穿过的通道)。检查评论,寻找一个好的解决方案 现在,让我们看看您提到的第一个解决方案,应用于这棵树 您的第一个解决方案基本上是a,这真的没有那么糟糕。这实际上是一个非常好的递归搜索。基本上,它说,“总是先采取最右边的方法。如果没有任何东西,回溯到第一个你可以直行或左行的地方,然后重复 深度优先搜索将按以下顺序搜索上述树:
A B D (backtrack) E H L (backtrack) M ** (backtrack) O (backtrack thrice) I
(backtrack thrice) C F (backtrack) G J
A (next level) B C (next level) D E F G (next level)
H I J (next level) L M (next level) ** O
请注意,您可以在找到**后立即停止
但是,当您实际编写深度优先搜索代码时,使用递归编程可以使一切变得更加简单。即使迭代方法也可以工作,而且您永远不必显式编程如何回溯。请查看链接文章以了解实现方法
另一种搜索树的方法是解决方案,它按深度搜索树。它将按以下顺序搜索上面的树:
A B D (backtrack) E H L (backtrack) M ** (backtrack) O (backtrack thrice) I
(backtrack thrice) C F (backtrack) G J
A (next level) B C (next level) D E F G (next level)
H I J (next level) L M (next level) ** O
请注意,由于迷宫的性质,宽度优先的平均检查节点数要高得多。宽度优先很容易实现,它有一个路径队列进行搜索,每次迭代都会从队列中弹出一条路径,“分解它”“通过在一个步骤后获取它可以转换为的所有路径,并将这些新路径放在队列的末尾。代码中没有明确的“下一级”命令,这些命令只是为了帮助理解
事实上,有一个整体。我刚才提到了两种最简单、最直接的方法
如果你的迷宫非常、非常长、很深,有循环和疯狂,而且很复杂,我建议使用这种算法,这是一种行业标准的寻路算法,它将广度优先搜索与启发式相结合……有点像“智能广度优先搜索”
它基本上是这样工作的:
抱歉,长度=p(我倾向于漫无边际)这是我最喜欢的算法之一
1) Move forward
2) Are you at a wall?
2a) If yes, turn left
3) Are you at the finish?
3a) If no, go to 1
3b) If yes, solved
一个有趣的方法,至少我觉得很有趣,就是使用细胞自动机。简言之,由3个“墙”单元包围的“空间”单元将变成“墙”单元。最后剩下的空间单元是通往出口的路径上的单元
如果你看一看贾斯汀在他的答案里写的树,你会发现叶子节点有三堵墙。修剪这棵树,直到你有一条路。只是个主意。为什么不以蒙特卡洛的方式扔一些机器人进去呢。 让我们称第一代机器人为gen0。 我们只保留gen0中的机器人,这些机器人具有以下连续道路:
-从头到尾
或者——从某一点到最后 我们在new ran中运行了新一代机器人
While Not At End
If Can Go North
Go North
ElseIf Can Go East
Go East
ElseIf Can Go South
Go South
ElseIf Can Go West
Go West
EndIf
Wend
SXXXXXXXXXXXXX
X X
X X
X X
XXX X
X X X
X XXXXXXXXXXX XXXE
X X
XXXXXXXXXXXXXXXXXXX
#ifndef vAlgorithms_Interview_graph_maze_better_h
#define vAlgorithms_Interview_graph_maze_better_h
static const int kMaxRows = 100;
static const int kMaxColumns = 100;
class MazeSolver
{
private:
char m_matrix[kMaxRows][kMaxColumns]; //matrix representation of graph
int rows, cols; //actual rows and columns
bool m_exit_found;
int m_exit_row, m_exit_col;
int m_entrance_row, m_entrance_col;
struct square //abstraction for data stored in every verex
{
pair<int, int> m_coord; //x and y co-ordinates of the matrix
square* m_parent; //to trace the path backwards
square() : m_parent(0) {}
};
queue<square*> Q;
public:
MazeSolver(const char* filename)
: m_exit_found(false)
, m_exit_row(0)
, m_exit_col(0)
, m_entrance_row(0)
, m_entrance_col(0)
{
ifstream file;
file.open(filename);
if(!file)
{
cout << "could not open the file" << endl << flush;
// in real world, put this in second phase constructor
}
init_matrix(file);
}
~MazeSolver()
{
}
void solve_maze()
{
//we will basically use BFS: keep pushing squares on q, visit all 4 neighbors and see
//which way can we proceed depending on obstacle(wall)
square* s = new square();
s->m_coord = make_pair(m_entrance_row, m_entrance_col);
Q.push(s);
while(!m_exit_found && !Q.empty())
{
s = Q.front();
Q.pop();
int x = s->m_coord.first;
int y = s->m_coord.second;
//check if this square is an exit cell
if(x == m_exit_row && y == m_exit_col)
{
m_matrix[x][y] = '>'; // end of the path
m_exit_found = true;
//todo: try breaking? no= queue wont empty
}
else
{
//try walking all 4 neighbors and select best path
//NOTE: Since we check all 4 neighbors simultaneously,
// the path will be the shortest path
walk_path(x-1, y, s);
walk_path(x+1, y, s);
walk_path(x, y-1, s);
walk_path(x, y+1, s);
}
} /* end while */
clear_maze(); //unset all previously marked visited shit
//put the traversed path in maze for printing
while(s->m_parent)
{
m_matrix[s->m_coord.first][s->m_coord.second] = '-';
s = s->m_parent;
} /* end while */
}
void print()
{
for(int i=0; i<rows; i++)
{
for(int j=0; j<cols; j++)
cout << m_matrix[i][j];
cout << endl << flush;
}
}
private:
void init_matrix(ifstream& file)
{
//read the contents line-wise
string line;
int row=0;
while(!file.eof())
{
std::getline(file, line);
for(int i=0; i<line.size(); i++)
{
m_matrix[row][i] = line[i];
}
row++;
if(line.size() > 0)
{
cols = line.size();
}
} /* end while */
rows = row - 1;
find_exit_and_entry();
m_exit_found = false;
}
//find and mark ramp and exit points
void find_exit_and_entry()
{
for(int i=0; i<rows; i++)
{
if(m_matrix[i][cols-1] == ' ')
{
m_exit_row = i;
m_exit_col = cols - 1;
}
if(m_matrix[i][0] == ' ')
{
m_entrance_row = i;
m_entrance_col = 0;
}
} /* end for */
//mark entry and exit for testing
m_matrix[m_entrance_row][m_entrance_col] = 's';
m_matrix[m_exit_row][m_exit_col] = 'e';
}
void clear_maze()
{
for(int x=0; x<rows; x++)
for(int y=0; y<cols; y++)
if(m_matrix[x][y] == '-')
m_matrix[x][y] = ' ';
}
// Take a square, see if it's the exit. If not,
// push it onto the queue so its (possible) pathways
// are checked.
void walk_path(int x, int y, square* parent)
{
if(m_exit_found) return;
if(x==m_exit_row && y==m_exit_col)
{
m_matrix[x][y] = '>';
m_exit_found = true;
}
else
{
if(can_walk_at(x, y))
{
//tag this cell as visited
m_matrix[x][y] = '-';
cout << "can walk = " << x << ", " << y << endl << flush;
//add to queue
square* s = new square();
s->m_parent = parent;
s->m_coord = make_pair(x, y);
Q.push(s);
}
}
}
bool can_walk_at(int x, int y)
{
bool oob = is_out_of_bounds(x, y);
bool visited = m_matrix[x][y] == '-';
bool walled = m_matrix[x][y] == '#';
return ( !oob && !visited && !walled);
}
bool is_out_of_bounds(int x, int y)
{
if(x<0 || x > rows || y<0 || y>cols)
return true;
return false;
}
};
void run_test_graph_maze_better()
{
MazeSolver m("/Users/vshakya/Dropbox/private/graph/maze.txt");
m.print();
m.solve_maze();
m.print();
}
#endif