迷宫问题(八方向)c++

系列文章目录

前言

八个方向的迷宫问题

一、题目描述

给定一个迷宫,左上角为入口,右下角为出口,求出行走路径。
一共八个方向:东、南、西、北、东北、东南、西北、西南,分别记为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;
}

总结

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值