系列文章目录
前言
八个方向的迷宫问题
一、题目描述
给定一个迷宫,左上角为入口,右下角为出口,求出行走路径。
一共八个方向:东、南、西、北、东北、东南、西北、西南,分别记为E S W N NE SE NW SW。
m*n的迷宫:
0 1 1 1 0 1 1 1
1 0 1 0 1 0 1 0
0 1 0 0 1 1 1 1
0 1 1 1 0 0 1 1
1 0 0 1 1 0 0 0
0 1 1 0 0 1 1 0
入口为左上角,出口为右下角。
有八个方向可以供选择。
上述0表示可走,1表示不可走。为方便处理,在迷宫周围加上一圈墙壁(即1、代表不可走),可省去边界检查。
之后得到一个(m+2)*(n+2)的迷宫,入口为(1,1),出口为(m,n)
1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 0 1 1 1 1
1 1 0 1 0 1 0 1 0 1
1 0 1 0 0 1 1 1 1 1
1 0 1 1 1 0 0 1 1 1
1 1 0 0 1 1 0 0 0 1
1 0 1 1 0 0 1 1 0 1
1 1 1 1 1 1 1 1 1 1
定义一个数组move表示移动方向,由0-7代表8个移动方向,每个方向都有垂直坐标和水平坐标。
搜索策略是先试探正北方向,然后顺时针试探其他方向
二、c++代码
1.使用栈
代码如下:
#include<iostream>
#include<stack>
using namespace std;
typedef struct {
int x;
int y;
}point;
int num_step = 0; //找到出口一共走了多少步
stack<point> result_path; //用一个栈保存有效的路径(即从入口到出口的路径)
int Maze[8][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1},
{1,1,0,1,0,1,0,1,0,1},
{1,0,1,0,0,1,1,1,1,1},
{1,0,1,1,1,0,0,1,1,1},
{1,1,0,0,1,1,0,0,0,1},
{1,0,1,1,0,0,1,1,0,1},
{1,1,1,1,1,1,1,1,1,1}}; //迷宫
point mov[8] = { { -1, -1 },
{ -1, 0 },
{ -1, 1 },
{ 0, -1 },
{ 0, 1 },
{ 1, -1 },
{ 1, 0 },
{ 1, 1 } }; //移动方向表,共8个方向,首先从正北开始 然后顺时针走其他方向
bool MazePath(int row, int column, int x, int y){ //(1,1)为迷宫入口
stack<point> process_path; //用一个栈保存走过的路径
bool flag; //是否存在一条从入口到出口的路径,如存在则flag为true,如不存在为false
point now; //设置当前所在位置为迷宫入口,即x,y
now.x = x;
now.y = y;
process_path.push(now); //将当前位置添加到process_path中
while (!process_path.empty()){
now = process_path.top(); //取栈顶元素
if (Maze[now.x][now.y] == 0){ //如果路可以走
result_path.push(now); //因为result_path为全局变量所以下面也用得到,画路径要用
Maze[now.x][now.y] = -1; //将有效路径的位置置为-1
}
flag = true;
for (int i = 0; i<8; i++){ //一共8个方向可以走
if (now.x + mov[i].x == row && now.y + mov[i].y == column)
return true; //到达终点.
if (Maze[now.x + mov[i].x][now.y + mov[i].y] == 0){ //如果道路可通
point temp;
temp.x = now.x + mov[i].x;
temp.y = now.y + mov[i].y;
process_path.push(temp);
flag = false;
}
}
if (flag){
process_path.pop();
result_path.pop();
}
}
return flag;
}
void PrintPath(int row, int column){
//输出从入口到出口的路径
point temp;
temp.x = row;
temp.y = column;
stack<point> pp;
pp.push(temp);
while (!result_path.empty()){
temp = result_path.top();
result_path.pop();
pp.push(temp);
}
while (!pp.empty()){
temp = pp.top();
cout << '(' << temp.x << ',' << temp.y << ')' << ' ';
num_step++;
pp.pop();
}
cout << endl;
cout <<"最短路径为:"<< num_step <<"步"<<endl;
}
int main(){
int row=6, column=8;
if (MazePath(row, column, 1, 1)){
cout << "YES" << endl;
PrintPath(row, column);
}
else cout << "NO" << endl;
return 0;
}
以上方法将有效路径的迷宫位置 置为-1,还有一种方式是另外设置一个矩阵Mark,用来标记有效路径,初始化为全零,有效位置 置1
#include<iostream>
#include<stack>
using namespace std;
typedef struct {
int x;
int y;
}point;
int num_step = 0; //找到出口一共走了多少步
stack<point> result_path; //用一个栈保存有效的路径(即从入口到出口的路径)
int Maze[8][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1},
{1,1,0,1,0,1,0,1,0,1},
{1,0,1,0,0,1,1,1,1,1},
{1,0,1,1,1,0,0,1,1,1},
{1,1,0,0,1,1,0,0,0,1},
{1,0,1,1,0,0,1,1,0,1},
{1,1,1,1,1,1,1,1,1,1}}; //迷宫
int Mark[8][10] = {0}; //将标记矩阵初始化为全零
point mov[8] = { { -1, -1 },
{ -1, 0 },
{ -1, 1 },
{ 0, -1 },
{ 0, 1 },
{ 1, -1 },
{ 1, 0 },
{ 1, 1 } }; //移动方向表,共8个方向,首先从正北开始 然后顺时针走其他方向
bool MazePath(int row, int column, int x, int y){ //(1,1)为迷宫入口
stack<point> process_path; //用一个栈保存走过的路径
bool flag; //是否存在一条从入口到出口的路径,如存在则flag为true,如不存在为false
point now; //设置当前所在位置为迷宫入口,即x,y
now.x = x;
now.y = y;
process_path.push(now); //将当前位置添加到process_path中
while (!process_path.empty()){
now = process_path.top(); //取栈顶元素
if (Maze[now.x][now.y] == 0 && Mark[now.x][now.y] == 0){ //如果路可以走
result_path.push(now); //因为result_path为全局变量所以下面也用得到,画路径要用
Mark[now.x][now.y] = 1;
}
flag = true;
for (int i = 0; i<8; i++){ //一共8个方向可以走
if (now.x + mov[i].x == row && now.y + mov[i].y == column)
return true; //到达终点.
if (Maze[now.x + mov[i].x][now.y + mov[i].y] == 0 && Mark[now.x + mov[i].x][now.y + mov[i].y] == 0){ //如果道路可通
point temp;
temp.x = now.x + mov[i].x;
temp.y = now.y + mov[i].y;
process_path.push(temp);
flag = false;
}
}
if (flag){
process_path.pop();
result_path.pop();
}
}
return flag;
}
void PrintPath(int row, int column){
//输出从入口到出口的路径
point temp;
temp.x = row;
temp.y = column;
stack<point> pp;
pp.push(temp);
while (!result_path.empty()){
temp = result_path.top();
result_path.pop();
pp.push(temp);
}
while (!pp.empty()){
temp = pp.top();
cout << '(' << temp.x << ',' << temp.y << ')' << ' ';
num_step++;
pp.pop();
}
cout << endl;
cout <<"最短路径为:"<< num_step <<"步"<<endl;
}
int main(){
int row=6, column=8;
if (MazePath(row, column, 1, 1)){
cout << "YES" << endl;
PrintPath(row, column);
}
else cout << "NO" << endl;
return 0;
}
2.递归
代码如下:
#include<iostream>
#include<stack>
using namespace std;
typedef struct {
int x;
int y;
}point;
int num_step = 0; //找到出口一共走了多少步
stack<point> result_path; //用一个栈保存有效的路径(即从入口到出口的路径)
int Maze[8][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1},
{1,1,0,1,0,1,0,1,0,1},
{1,0,1,0,0,1,1,1,1,1},
{1,0,1,1,1,0,0,1,1,1},
{1,1,0,0,1,1,0,0,0,1},
{1,0,1,1,0,0,1,1,0,1},
{1,1,1,1,1,1,1,1,1,1}}; //迷宫
point mov[8] = { { -1, -1 },
{ -1, 0 },
{ -1, 1 },
{ 0, -1 },
{ 0, 1 },
{ 1, -1 },
{ 1, 0 },
{ 1, 1 } }; //移动方向表,共8个方向,首先从正北开始 然后顺时针走其他方向
bool MazePath(int row, int column, int x, int y){ //递归
point temp;
temp.x = x;
temp.y = y;
Maze[x][y] = -1;
result_path.push(temp);
for(int i=0;i<8;i++)
{
if(x+mov[i].x == row && y+mov[i].y == column)
return true;
if(Maze[x+mov[i].x][y+mov[i].y] == 0)
{
if(MazePath(row,column,x+mov[i].x,y+mov[i].y))
return true;
}
}
result_path.pop();
return false;
}
void PrintPath(int row, int column){
//输出从入口到出口的路径
point temp;
temp.x = row;
temp.y = column;
stack<point> pp;
pp.push(temp);
while (!result_path.empty()){
temp = result_path.top();
result_path.pop();
pp.push(temp);
}
while (!pp.empty()){
temp = pp.top();
cout << '(' << temp.x << ',' << temp.y << ')' << ' ';
num_step++;
pp.pop();
}
cout << endl;
cout <<"最短路径为:"<< num_step <<"步"<<endl;
}
int main(){
int row=6, column=8;
if (MazePath(row, column, 1, 1)){
cout << "YES" << endl;
PrintPath(row, column);
}
else cout << "NO" << endl;
return 0;
}