BFS/DFS

一、BFS

  BFS的实现是基于队列的,每次push一层的所有可用元素后再依次push每个元素的下一层后pop当前元素,直到队列为空。

  以一个ACM题目进行说明——红与黑。

  问题描述

  有一个长方形的房间,上面铺着方砖。每块瓷砖都是红色或黑色的。一个男人站在一块黑色的瓷砖上。从一个瓦片,他可以移动到四个相邻瓦片之一。但他不能在红瓷砖上移动,他只能在黑色瓷砖移动。
  写一个程序来计算他可以通过重复上述动作到达的黑色瓷砖的数量。
  

  输入
  输入由多个数据集组成。一个数据集从一条包含两个正整数W和H的线开始;W和H分别是x和y方向上的分片数。W和H不超过20。
  数据集中还有H行,每行包含W个字符。每个字符表示瓷砖的颜色,如下所示。
   "."-黑色
  “#”-红色
  “@”-一个站在在黑色瓷砖上的人(在一个数据集中恰好出现一次)
  

  输出
  对于每个数据集,您的程序应该输出一行,其中包含他可以从初始位置(包括其自身)到达的黑色瓷砖数。
  

  样本输入
  
6 9
  ....#.
  .....#
  ......
  ......
  ......
  ......
  ......
  #@...#
  .#..#.
  0 0

  
    
输出
  
45
  

  思路

  以(wx,wy)形式表示坐标。

  1. 初始为(8,2),加入队列,邻接可用的有(7,2)、(8,3),弹出(8,2),加入(7,2)、(8,3)到队列。当前队列为{(7,2)、(8,3)}。

  2. (7,2)邻接可用的有(7,1)、(6,2)、(7,3),弹出(7,2),加入(7,1)、(6,2)、(7,3)到队列。当前队列为{(8,3)、(7,1)、(6,2)、(7,3)}

  ……

  最后pop出无路可走节点,结束。

  代码

#include <iostream>
#include <queue>
using namespace std;

char room[23][23];
int direction[4][2] = { {-1,0},{0,-1},{1,0},{0,1} };//左上右下
//Wx总行数 Wy总列数 num能够走到的黑瓷砖的个数
int Wx, Wy, num;
//检查当前位置是否在区域内
#define CHECK(x,y)(x>=0&&x<Wx&&y>=0&&y<Wy)
struct node { int x, y; };

void BFS(int x, int y) {
    num = 1;
    queue<node> q;
    node start,next;
    start.x = x;
    start.y = y;
    q.push(start);
    for (int i = 0; i < 4; i++) {
        while (!q.empty()) {
            start = q.front();
            q.pop();
            cout << "    ->      "<< start.y + 1 << " " << start.x + 1 ;
            //枚举与当前节点紧挨的有多少黑色节点,加入队列
            for (int i = 0; i < 4; i++) {
                next.x = start.x + direction[i][0];
                next.y = start.y + direction[i][1];
                if (CHECK(next.x, next.y) && room[next.x][next.y] == '.') {
                    room[next.x][next.y] = '#';
                   
                    num++;
                    q.push(next);
                }
            }
        }
        
    }
}


int main()
{
    int startX, startY;

    while (scanf("%d %d", &Wx, &Wy) != EOF) {
        for (int y = 0; y < Wy; y++) {
            for (int x = 0; x < Wx; x++) {
                cin >> room[x][y];//第x行第y列
                if (room[x][y] == '@') {
                    startX = x;
                    startY = y;

                }
            }
        }
        cout << "BFS:" << endl;
        BFS(startX, startY);
        cout << endl;
        cout << num << endl;
    }
}        

 

二、DFS

  DFS与BFS不同点在于,BFS采用队列而不是递归从而对当前节点所邻接的所有可用节点都能够依次进行遍历,遍历完了之后才是遍历第二层;

  DFS查找到当前节点的一个可用节点后会继续往下对可用节点进行相同操作,而不是接着寻找当前节点的下一个可用节点。

  代码

  

void DFS(int x, int y) {
    room[x][y] = '#';
    for (int i = 0; i < 4; i++) {
        int newx = x + direction[i][0];
        int newy = y + direction[i][1];
        if (CHECK(newx, newy) && room[newx][newy] == '.') {
            num++;
            cout << newy+1 << " " << newx+1 << "    ->      ";
            //这里采用递归,就是深度优先的核心
            DFS(newx, newy);
            cout << y+1 << " "<<x+1 << "    ->      ";
        }
    }
    
}    

 

posted @ 2021-03-31 20:05  徐不二  阅读(90)  评论(0)    收藏  举报