迷宫问题的深度优先法

题目:迷宫-深度策略

一个陷入迷宫的老鼠如何找到出口的问题。老鼠希望系统性地尝试所有的路径之后走出迷宫。如果它到达一个死胡同,将原路返回到上一个位置,尝试新的路径。在每个位置上老鼠可以向八个方向运动,顺序是从正东开始按照顺时针进行。无论离出口多远,它总是按照这样的顺序尝试,当到达一个死胡同之后,老鼠将进行“回溯”。迷宫只有一个入口,一个出口,设计程序要求输出迷宫的一条通路。迷宫用二维存储结构表示,1表示障碍,0表示通路;采用回溯法设计求解通路的算法。要求如下:
1、实现栈的相关操作; 2、利用栈实现回溯算法输出路径;

输入格式: 输入包括三部分: 第一个输入是迷宫大小;第二个输入是迷宫的状态;第三个输入是入口和出口位置

输出格式: 反向输出探索的路径,注意包括入口和出口位置。每个位置之间用分号;分隔。

输入样例: 9 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 0
0 1 1 1 1 1 0 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 7 7 输出样例: 7 7;6 6;5 7;4 6;4 5;3 4;2
5;2 4;2 3;1 2;1 1;

解题思路:
迷宫问题是数据结构中常见的一种类型,也可以当作是网格类问题的一种,对于这种问题,一般有深度优先DFS广度优先BFS方法

下面介绍用栈知识实现深度优先DFS的方法,使用栈解决需要用到栈的基本操作:

  • 的建立,初始化,入栈,出栈,栈的判空等。
  • 迷宫的数据结构:用二维数组表示迷宫结构
  • 回溯算法:使用栈实现回溯,探索迷宫所有可能的路径,遇到障碍时回溯。

下面给出程序的实现及步骤分析:

  • 首先时栈的基本操作的实现
typedef int DataType;
struct Node//栈节点类型定义
{
    DataType data;
    struct Node* next;
};

typedef struct Node* PNode;
typedef struct Node* top, * LinkStack;

//空栈创建
LinkStack SetNullStack_Link()
{
    LinkStack top = (LinkStack)malloc(sizeof(struct Node));
    if (top != NULL)
        top->next = NULL;
    else
        printf("Alloc failure");
    return top;
}

//栈判空
int IsNullStack_link(LinkStack top)
{
    if (top->next == NULL)
        return 1;
    else
    return 0;
}

//进栈函数
void Push_link(LinkStack top, DataType x)
{
    PNode p;
    p = (PNode)malloc(sizeof(struct Node));
    if (p == NULL)
        printf("Alloc failure");
    else
    {
        p->data = x;
        p->next = top->next;
        top->next = p;
    }
}

//出栈函数
void Pop_link(LinkStack top)
{
    PNode p;
    p = (PNode)malloc(sizeof(struct Node));
    if (IsNullStack_link(top))
        printf("It is empty stack!");
    else
    {
        p = top->next;
        top->next = p->next;
        free(p);
    }
}

//取栈顶元素
DataType Pop_seq_return(LinkStack top)
{
    if (IsNullStack_link(top))
        printf("It is empty stack!");
    else
        return top->next->data;
}
  • 接下来是使用二维数组实现迷宫结构的定义
typedef struct MAZE_STRU//迷宫结构体定义
{
    int size;//迷宫大小
    int** data;//二维数组迷宫结构
}Maze;

Maze* InitMaze(int size)//迷宫初始化
{
    int i;
    Maze* maze;
    maze= (Maze*)malloc(sizeof(Maze));
    maze->size = size;//迷宫的大小
    
    maze->data = (int**) malloc(sizeof(int*) * maze->size);//分配迷宫空间
    for (i = 0; i < maze->size;i++)
    {
        maze->data[i] = (int*)malloc(sizeof(int) * maze->size);
    }
    return maze;
}

//读取迷宫结构
void ReadMaze(Maze* maze)
{
    int i, j;
    for (i = 0; i < maze->size; i++)
    {
        for (j = 0; j < maze->size; j++)
        {
            scanf("%d", &maze->data[i][j]);
        }
    }
}

//显示迷宫结构
void WriteMaze(Maze* maze)
{
    int i, j;
    for (i = 0; i < maze->size; i++)
    {
        for (j = 0; j < maze->size; j++)
        {
        printf("%d ",maze->data[i][j]);
        }
    printf("\n");
    }
}

  • 最后是dfs算法实现
int MazeDFS(int entryX, int entryY, int exitX, int exitY, Maze* maze)
{
    int direction[8][2] = { {0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1} };//方向数组
    
    LinkStack linkStackX = NULL;
    LinkStack linkStackY = NULL;//两个栈,分别报讯路径中点(x,y)值
    
    int posX, posY;//临时变量,存放点坐标(x,y)
    int preposX, preposY;//存放当前节点的前一个节点
    
    int** mark;//标记二维数组,用于标记是否走过
    
    int i, j;//循环变量
    int mov;//移动方向
    
    mark = (int**)malloc(sizeof(int*) * maze->size);//分配空间并赋值
    for (i = 0; i < maze->size; i++)
    	mark[i] = (int*)malloc(sizeof(int) * maze->size);
    
    for (i = 0; i < maze->size; i++)//所有元素设置初值
    {
    	for (j = 0; j < maze->size; j++)
    		mark[i][j]=0;
    }
    
    linkStackX = SetNullStack_Link();//初始化栈
    linkStackY = SetNullStack_Link();
    
    mark[entryX][entryY] = 1;//入口点设置标志位
    
    Push_link(linkStackX, entryX);//入口点入栈
    Push_link(linkStackY, entryY);
    
    while (!IsNullStack_link(linkStackX))//栈不为空且没找到出口点
    {
	    preposX = Pop_seq_return(linkStackX);
	    preposY = Pop_seq_return(linkStackY);
	    Pop_link(linkStackX);
	    Pop_link(linkStackY);
	    mov = 0;
        while (mov < 8)
		{
		    posX = preposX + direction[mov][0];//改变位置
		    posY = preposY + direction[mov][1];
		    if (posX == exitX && posY == exitY)//到达终点
		    	{
				    Push_link(linkStackX, preposX);
				    Push_link(linkStackY, preposY);
				    printf("%d %d;", exitX, exitY);//打印入口
	    			while (!IsNullStack_link(linkStackX))//将路径逆序输出
				    {
				    posX = Pop_seq_return(linkStackX);//取栈顶元素
				    posY = Pop_seq_return(linkStackY);//
				    Pop_link(linkStackX);//出栈
				    Pop_link(linkStackY);
				    printf("%d %d;", posX, posY);//输出栈顶元素
				    }
	    			return 1;
	    		 }
		    if (maze->data[posX][posY] == 0 && mark[posX][posY] == 0)//未走过且通路
		    {
			    mark[posX][posY] = 1;
			    Push_link(linkStackX, preposX);//入栈
			    Push_link(linkStackY, preposY);
			    preposX = posX;
			    preposY = posY;
			    mov = 0;//往前走,重新从0开始搜索
		    }
		    else
		    	mov++;
		}
    }
    return 0;
}

  • 主函数
int main()
{
	Maze* maze;
	int mazeSize;//迷宫大小
	int entryX, entryY, exitX, exitY;
	int find = 0;
	scanf("%d", &mazeSize);
	entryX = 0; entryY = 0;
	exitX = mazeSize - 1; 
	exitY = exitX;
	if(mazeSize)
	    maze = InitMaze(mazeSize);
	ReadMaze(maze);
	scanf("%d%d%d%d", &entryX, &entryY, &exitX, &exitY);//深度优先搜索
	find = MazeDFS(entryX, entryY, exitX, exitY, maze);
	if (!find)
		printf("找不到路径!\n");
	return 0;
}

在这里插入图片描述

在这里插入图片描述
** 谢 谢 点 赞 支 持 o( ̄︶ ̄)o**

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值