题目:迷宫-深度策略
一个陷入迷宫的老鼠如何找到出口的问题。老鼠希望系统性地尝试所有的路径之后走出迷宫。如果它到达一个死胡同,将原路返回到上一个位置,尝试新的路径。在每个位置上老鼠可以向八个方向运动,顺序是从正东开始按照顺时针进行。无论离出口多远,它总是按照这样的顺序尝试,当到达一个死胡同之后,老鼠将进行“回溯”。迷宫只有一个入口,一个出口,设计程序要求输出迷宫的一条通路。迷宫用二维存储结构表示,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**