這個題目就是考了圖的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;
}