走迷宫
一个网格迷宫又n行m列的单元格组成,每个单元格要么是空地(用0来表示),要么是障碍物(用1来表示)。你的任务是找到一条从起点到终点的最短移动序列。起点和终点保证是空地。n, m<=100 。为了简单我的程序直接给出迷宫图,且大小为 7*7。
#include <stdio.h>
#define MAX 100
#define N 7
int maze[N][N] =
{//1代表障碍物
{0,0,0,1,0,0,0},
{0,0,1,0,0,0,0},
{0,0,1,0,1,1,0},
{0,0,1,0,0,0,0},
{0,0,0,0,1,0,0},
{0,0,1,0,0,0,0},
{0,0,0,0,0,0,0}
};
int vis[N][N], fa[N][N], last_dir[N][N];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int q[MAX];
int dir[MAX];
char name[4] = {'U','R','D','L'};
void bfs(int x, int y)
{
int u = x * N + y;
int front = 0, rear = 0;
int nx, ny, d, v;
q[rear++] = u;
fa[x][y] = u;
vis[x][y] = 1;//千万别忘记了标记此处的访问记录
while (rear > front)
{
u = q[front++];
x = u / N; y = u % N;
for (d=0; d<4; d++)
{//代表四个方向
nx = x + dx[d];
ny = y + dy[d];
if (nx>=0 && nx<N && ny>=0 && ny<N && !maze[nx][ny] && !vis[nx][ny])
{//(nx, ny)没有出界,不是障碍且没被访问过
v = nx * N + ny;
q[rear++] = v;
fa[nx][ny] = u;//记录(nx, ny)的前趋
vis[nx][ny] = 1;//访问记录
last_dir[nx][ny] = d;//记录从(x, y)到(nx, ny)的方向
}
}
}
}
/*递归实现路径输出
void print_path(int x, int y)
{
int fx = fa[x][y] / N;
int fy = fa[x][y] % N;
if (fx != x || fy != y)
{
print_path(fx, fy);
putchar(name[last_dir[x][y]]);
}
}
*/
//显式栈实现路径输出
void print_path(int x, int y)
{
int c = 0;
for (;;)
{
int fx = fa[x][y] / 7;
int fy = fa[x][y] % 7;
if (fx == x && fy == y)
break;
dir[c++] = last_dir[x][y];
x = fx;
y = fy;
}
while (c--)
{
putchar(name[dir[c]]);
}
}
int main(void)
{
int i, j;
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
printf("%d", maze[i][j]);
printf("\n");
}
printf("从入口到出口迷宫路径:\n");
bfs(0, 0); //广搜((0, 0)迷宫入口)
print_path(0, 6); //打印行走方向((0, 6)为迷宫出口)
printf("\n");
return 0;
}
看刘汝佳的代码基本上不用注释,一遍遍的看下去就会有收获,看的越多越觉得妙不可言。
走迷宫就是把一个用三个图(数组)存放一个图(迷宫)的信息,其中vis是标记该网格是否访问过,避免重复访问造成死循环,fa是记录该网格的前趋,last_dir存放的是前趋到该网格的前进方向。
浙公网安备 33010602011771号