POJ3083 -- BFS和DFS

这个题目就是考了图的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;
}


 

猜你喜欢

转载自blog.csdn.net/genius9_9/article/details/46358285