迷宫最短路径涉及BFS和队列的使用,本文不用STL实现这道题。
【题目描述】
图片来源于《挑战程序设计竞赛(第2版)》:
【算法分析】
首先将起点存入队列;
每次先从队列中取出一个点,然后遍历其上下左右四个方向上的非墙壁点(当然同时也要判断四个方向都在正确范围内)。对于每一个被遍历的点,先判断其是不是终点,如果不是,则将此点加入队列,然后处理下一个遍历到的点。对于每个被遍历的点,同时还要存储从开始点到达其的步数,存储结构是一个数组,数组用INF进行初始化。
本题较为麻烦,要进行队列的正确操作,如果用STL还比较简单。但为了锻炼编程能力,博主决定这次不用STL。
【示例代码】
#include<stdio.h>
#define MAX_N 100
#define MAX_M 100
#define INF 100000000 //记住这个,INF通常赋值为100000000
//队列存储结构
int queue_x[MAX_N*MAX_M];
int queue_y[MAX_N*MAX_M];
int front,rear;
void enqueue(int x,int y){
queue_x[rear++]=x;
queue_y[rear++]=y;
}
int dequeue_x(){
return queue_x[front++];
}
int dequeue_y(){
return queue_y[front++];
}
int main(){
int N,M;
int step[MAX_N][MAX_M]; //存储起点到当前点的步数,初始化为超大数(代表不可达)
char map[MAX_N][MAX_M];
int start_x,start_y; //存储起点的坐标
char ch;
int current_x,current_y;
while(scanf("%d %d",&N,&M)==2){
getchar();
for(int i=0;i<N;i++){
for(int j=0;j<M;j++){
// scanf("%c",&map[i][j]); //这样输入也是可以的,博主想试一下getchar()
ch=getchar();
if(ch=='S'){ //不要将'S'写成"S"
start_x=i;
start_y=j;
}
map[i][j]=ch;
}
getchar();
}
//初始化step数组
for(int i=0;i<N;i++){
for(int j=0;j<M;j++){
step[i][j]=INF;
}
}
//初始化队列
front=0;
rear=0;
//核心算法
enqueue(start_x,start_y); //将起点加入队列
step[start_x][start_y]=0;
while(map[current_x=dequeue_x()][current_y=dequeue_y()]!='G'){
int dx,dy;
// for(dx=-1;dx<=1;dx++){ // 这种写法是错误的,因为它用来遍历八个方向
// for(dy=-1;dy<=1;dy++){
for(dx=-1,dy=0;dx<=1;dx+=2){
int x=current_x+dx;
int y=current_y+dy;
if(x>=0&&x<N&&y>=0&&y<M){ //判断未出界
if((map[x][y]=='G'||map[x][y]=='.')&&step[x][y]==INF){
step[x][y]=step[current_x][current_y]+1;
enqueue(x,y);
}
}
}
for(dy=-1,dx=0;dy<=1;dy+=2){
int x=current_x+dx;
int y=current_y+dy;
if(x>=0&&x<N&&y>=0&&y<M){ //判断未出界
if((map[x][y]=='G'||map[x][y]=='.')&&step[x][y]==INF){
step[x][y]=step[current_x][current_y]+1;
enqueue(x,y);
}
}
}
}
//回答问题
printf("%d\n",step[current_x][current_y]);
}
return 0;
}