题目要求
问题描述:编写一个程序求解迷宫问题。迷宫由m行n列的二维数组设置,0表示无障碍,1表示有障碍。设入口为(1, 1), 出口为(m, n), 每次只能从一个无障碍单元移到周围四个方向上任一无障碍单元。编程给出通过路径或无法通行的信息。
基本要求:
(1)输出迷宫的所有路径;
(2)筛选出最短路径。
算法
对迷宫递归地进行深度优先遍历
代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_Node 50
#define MAX_Path 50
typedef struct {
int x, y;
}Node;
typedef struct {
Node data[MAX_Node];
int len;
}Path;
typedef struct {
Path data[MAX_Path];
int num;
}PASH;
Node dir[4] = { {-1,0},{1,0},{0,-1},{0,1} }; //上下左右四个方向
Path p = { {{0,0}},0 }; //存放一条路径的各个坐标
PASH pash = { { { {{0,0}},0 } } , 0 }; //存放所有路径
int m = 0, n = 0; //m行n列的迷宫
//判断是否越界,若越界返回true
bool Over(int x, int y) {
if ((x >= 1 && x <= m) && (y >= 1 && y <= n)) {
return false;
}
else return true;
}
//判断当前的路径中是否已存在该坐标,若已存在返回true
bool visited(Path p, int x, int y) {
for (int i = 0; i < p.len; i++) {
if (x == p.data[i].x && y == p.data[i].y)
return true;
}
return false;
}
//递归
void DFS(char **map, int x, int y) {
//找到终点了
if (x == m && y == n) {
p.data[p.len].x = x;
p.data[p.len++].y = y;
pash.data[pash.num++] = p; //将该路径存放到pash中
}
//注意判断条件的顺序, 若map[x][y] == '0'放第一个可能会导致数组越界
else if ( !Over(x, y) && map[x][y] == '0' && !visited(p, x, y) ) {
for (int i = 0; i < 4; i++) {
//将当前坐标存放到p中
if (!visited(p, x, y)) {
p.data[p.len].x = x;
p.data[p.len++].y = y;
}
//上下左右四个方向依次递归
DFS(map, x + dir[i].x, y + dir[i].y);
//回溯
p.len--;
}
}
}
void print(char **map, PASH pash) {
if (pash.num == 0)
printf("无法通行!\n");
else {
for (int i = 0; i < pash.num; i++) {
printf("第%d条路径: ", i + 1);
for (int j = 0; j < pash.data[i].len; j++) {
printf("(%d, %d) -> ", pash.data[i].data[j].x, pash.data[i].data[j].y);
}
printf("END\n");
for (int k = 1; k <= m; k++) {
for (int h = 1; h <= n; h++) {
if (visited(pash.data[i], k, h))
printf("* ");
else
printf("%c ", map[k][h]);
}
printf("\n");
}
}
int s = pash.data[0].len;
int ii = 0;
for (int i = 1; i < pash.num; i++) {
if (pash.data[i].len < s) {
s = pash.data[i].len;
ii = i;
}
}
printf("\n最短路径为第%d条,长度为%d\n", ii + 1, pash.data[ii].len);
for (int j = 0; j < pash.data[ii].len; j++) {
printf("(%d, %d) -> ", pash.data[ii].data[j].x, pash.data[ii].data[j].y);
}
printf("END\n");
for (int k = 1; k <= m; k++) {
for (int h = 1; h <= n; h++) {
if (visited(pash.data[ii], k, h))
printf("* ");
else
printf("%c ", map[k][h]);
}
printf("\n");
}
}
}
int main(){
printf("请输入迷宫的行列:");
scanf("%d %d", &m, &n);
//二级指针创建动态数组
char** map = (char**)malloc(sizeof(char*) * (m+1));
for (int i = 0; i < m+1; i++) {
*(map + i) = (char*)malloc(sizeof(char) * (n+1));
}
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
map[i][j] = '0';
}
}
for (int i = 1; i <= m; i++) {
printf("输入第%d行:\n", i);
for (int j = 1; j <= n; j++) {
getchar();
scanf("%c", &map[i][j]);
}
}
printf("已创建迷宫:\n");
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
printf("%c ", map[i][j]);
}
printf("\n");
}
DFS(map, 1, 1);
print(map, pash);
return 0;
}