这个题目就是考了图的BFS和DFS。
BFS用于求最短路径,这个非常简单。 DFS用于求左优先和右优先的路径,难点在于它的下一步方向是由上一步的方向确定的,因此每一步我们都需要确定当前的正方向。
一.在这里,我们定义了一个数据类型,用于存放迷宫中点的坐标以及当前行走的步数。
typedef struct Data{
int row;
int col;
int step;
}Data;
二.BFS中,我们定义的循环队列数组里存放的就是Data数据类型,每次走过了该点,需要标注一下,以后就不再走了。
typedef struct que{
Data data[MAX];
int front;
int rear;
}que;
void BFS(que* q ){
while(q->front != q->rear){
Data d =deQ(q);
if(d.row==end.row && d.col==end.col){ //到达终点
short_count = d.step;
return 0;
}
Data temp;
if(d.row>0 && maze[d.row-1][d.col]==1){ //迷宫向上走一步
temp.row = d.row-1;
temp.col = d.col;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row-1][d.col]= 0; //走过了置0
}
if(d.row < row-1 && maze[d.row+1][d.col]==1){ //迷宫向下走一步
temp.row = d.row+1;
temp.col = d.col;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row+1][d.col]= 0; //走过了置0
}
if(d.col > 0 && maze[d.row][d.col-1]==1){ //迷宫向左走一步
temp.row = d.row;
temp.col = d.col-1;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row][d.col-1]= 0; //走过了置0
}
if(d.col < col-1 && maze[d.row][d.col+1]==1){ //迷宫向右走一步
temp.row = d.row;
temp.col = d.col+1;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row][d.col+1]= 0; //走过了置0
}
}
}
三。DFS求左优先路径。
1. 在这里我们通过d的值来判断当前的正方向。
2.根据d值的不同,来选取不同的遍历顺序。(左优先的情况)
3.根据起点S来判断,第一个正方向d值。
题中:Exactly one 'S' and one 'E' will be present in the maze, and they will always be located along one of the maze edges and never in a corner. The maze will be fully enclosed by walls ('#'), with the only openings being the 'S' and 'E'.
也就是说,起点S一定位于迷宫的某条边上,且迷宫的四周都是被墙所环绕的,所以起点S在第一步时,只有一个方向可以走(与左右优先无关),因此,我们只需要根据起点S在哪一条边,则可以判断第一个方向值。
//根据起点位置,判断d值,即起点的当前正方向,第一步与左优先和右优先无关
int d;
Data temp;
if(start.row == row-1){ //起点位于迷宫的最下面一行,则正方向向上,,下一步一定是往上走的。
d=0;
temp.row=start.row-1;
temp.col = start.col;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}else if(start.col ==0 ){ //起点位于迷宫的最左边那一列, 则正方向向右,下一步一定是向右走
d=1;
temp.row = start.row;
temp.col = start.col+1;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}else if(start.row == 0) { //起点位于迷宫的第一行 ,则正方向向下,下一步一定是向下走
d=2;
temp.row = start.row+1;
temp.col = start.col;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}else if(start.col == col-1){ //起点位于迷宫的最右边那一列,则正方向是向左,下一步一定是向左走
d=3;
temp.row=start.row;
temp.col = start.col-1;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}
4.附上DFS的代码,通过递归找到终点就返回。
在case语句中,用了If...else if...else if....语句。
因为在这里是一条路走到底,必然可以到达终点。
而在其他迷宫的DFS算法中,有的时候走不通了,需要尝试另外一路径,此时则用到了for()语句循环或者if...if...if...语句。
void DFS_Left(Data data, int direct){
//left_count++;
if(data.col==end.col && data.row==end.row){//到达终点返回
left_count = data.step;
return;
}
Data temp;
switch(direct){
case 0:{ //正方向:向上, 按照左上右下的优先顺序行走
if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}
break;
}
case 1:{ //正方向:向右, 按照上右下左的优先顺序行走
if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}
break;
}
case 2:{ //正方向:向下,按照右下左上的优先顺序行走
if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}
break;
}
case 3:{ //正方向:向左,按照下左上右的优先顺序行走
if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}
break;
}
}
}
5.在进行右优先遍历的时候, 假如此时正方向向上,遍历的优先顺序是: 右 - 上 - 左 - 下, 而不是右 - 下 - 左 - 上。
四。附上全部源码。
#include <stdio.h>
#include <stdlib.h>
int maze[40][40];
int left_count,right_count,short_count;
#define MAX 120
typedef struct Data{
int row;
int col;
int step;
}Data;
Data start; //定义起点
Data end; //定义终点
int row ,col;
typedef struct que{
Data data[MAX];
int front;
int rear;
}que;
que* initQue(){
que* q = (que*) malloc(sizeof(que));
memset(q,0,sizeof(que));
return q;
}
int enQ(que* q , Data d){
if((q->rear+1)%MAX == q->front){ //队满返回0
return 0;
}
q->data[q->rear].row = d.row; //将X/Y坐标输入队列
q->data[q->rear].col = d.col;
q->data[q->rear].step = d.step;
q->rear =(q->rear+1)%MAX;
return 1;
}
Data deQ(que*q){
/*if(q->front == q->rear){ //队空,返回NULL
return NULL;
}*/
Data d = q->data[q->front];
q->front = (q->front+1)%MAX;
return d;
}
void BFS(que* q ){
while(q->front != q->rear){
Data d =deQ(q);
if(d.row==end.row && d.col==end.col){ //到达终点
short_count = d.step;
return 0;
}
Data temp;
if(d.row>0 && maze[d.row-1][d.col]==1){ //迷宫向上走一步
temp.row = d.row-1;
temp.col = d.col;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row-1][d.col]= 0; //走过了置0
}
if(d.row < row-1 && maze[d.row+1][d.col]==1){ //迷宫向下走一步
temp.row = d.row+1;
temp.col = d.col;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row+1][d.col]= 0; //走过了置0
}
if(d.col > 0 && maze[d.row][d.col-1]==1){ //迷宫向左走一步
temp.row = d.row;
temp.col = d.col-1;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row][d.col-1]= 0; //走过了置0
}
if(d.col < col-1 && maze[d.row][d.col+1]==1){ //迷宫向右走一步
temp.row = d.row;
temp.col = d.col+1;
temp.step = d.step+1;
enQ(q,temp);
maze[d.row][d.col+1]= 0; //走过了置0
}
}
}
//1.正方向:向上d=0; 2.正方向:向右d=1 3.正方向:向下d=2 4.正方向:向左d=3
void DFS_Left(Data data, int direct){
//left_count++;
if(data.col==end.col && data.row==end.row){
left_count = data.step;
return;
}
Data temp;
switch(direct){
case 0:{ //正方向:向上, 按照左上右下的优先顺序行走
if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}
break;
}
case 1:{ //正方向:向右, 按照上右下左的优先顺序行走
if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}
break;
}
case 2:{ //正方向:向下,按照右下左上的优先顺序行走
if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}
break;
}
case 3:{ //正方向:向左,按照下左上右的优先顺序行走
if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,2);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Left(temp,3);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Left(temp,0);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Left(temp,1);
}
break;
}
}
}
void DFS_Right(Data data, int direct){
if(data.col==end.col && data.row==end.row){
right_count = data.step;
return;
}
Data temp;
switch(direct){
case 0:{ //正方向:向上, 按照右上左下的优先顺序行走
if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Right(temp,1);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,0);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Right(temp,3);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,2);
}
break;
}
case 1:{ //正方向:向右, 按照下右上左的优先顺序行走
if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,2);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Right(temp,1);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,0);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Right(temp,3);
}
break;
}
case 2:{ //正方向:向下,按照左下右上的优先顺序行走
if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Right(temp,3);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,2);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Right(temp,1);
}else if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,0);
}
break;
}
case 3:{ //正方向:向左,按照上左下右的优先顺序行走
if(data.row>0 && maze[data.row-1][data.col]==1){ //迷宫向上走一步 ,此时正方向向上,即d=0
temp.row = data.row-1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,0);
}else if(data.col > 0 && maze[data.row][data.col-1]==1){ //迷宫向左走一步,此时正方向为向左,即d=3
temp.row = data.row;
temp.col = data.col-1;
temp.step = data.step+1;
DFS_Right(temp,3);
}else if(data.row < row-1 && maze[data.row+1][data.col]==1){ //迷宫向下走一步,其实就是往回走,此时正方向向下,、即d=2
temp.row = data.row+1;
temp.col = data.col;
temp.step = data.step+1;
DFS_Right(temp,2);
}else if(data.col < col-1 && maze[data.row][data.col+1]==1){ //迷宫向右走一步,此时正方向为向右,即d=1
temp.row = data.row;
temp.col = data.col+1;
temp.step = data.step+1;
DFS_Right(temp,1);
}
break;
}
}
}
int main()
{
int n;
//freopen("input.txt","r",stdin);
scanf("%d",&n);
int i =0;
for(i=0;i<n;i++){
memset(maze,0,sizeof(maze)); //迷宫初始化为0,不能初始化为1,每个值会认为是00000001 00000001 00000001
left_count =1;
right_count=1;
short_count=0;
scanf("%d%d",&col,&row);
int j,k;
for(j=0;j<row;j++){
for(k=0;k<col;k++){
char c;
scanf("%c",&c);
while(c=='\n' || c==' '){
scanf("%c",&c);
}
if(c=='.'){
maze[j][k]=1; //空地为1
}else if(c== 'S'){
maze[j][k] = 1; //起点为1,并记录起点坐标
start.row = j;
start.col =k;
start.step = 1;
}else if(c=='E'){
maze[j][k]=1; //终点为1,并记录终点坐标
end.row =j;
end.col = k;
end.step=0;
}
}
}
//根据起点位置,判断d值,即起点的当前正方向,第一步与左优先和右优先无关
int d;
Data temp;
if(start.row == row-1){ //起点位于迷宫的最下面一行,则正方向向上,,下一步一定是往上走的。
d=0;
temp.row=start.row-1;
temp.col = start.col;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}else if(start.col ==0 ){ //起点位于迷宫的最左边那一列, 则正方向向右,下一步一定是向右走
d=1;
temp.row = start.row;
temp.col = start.col+1;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}else if(start.row == 0) { //起点位于迷宫的第一行 ,则正方向向下,下一步一定是向下走
d=2;
temp.row = start.row+1;
temp.col = start.col;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}else if(start.col == col-1){ //起点位于迷宫的最右边那一列,则正方向是向左,下一步一定是向左走
d=3;
temp.row=start.row;
temp.col = start.col-1;
temp.step = start.step+1;
DFS_Left(temp,d);
DFS_Right(temp,d);
}
printf("%d %d ",left_count,right_count);
que* q = initQue();
enQ(q,start);
BFS(q);
printf("%d\n",short_count);
}
return 0;
}