广度优先搜索(breadth_first search)

广度优先搜索用队列(边进边出)

1. 日字形走法(象棋)

题目:
Input

There are multiple test cases.

The first line contains an integer T, indicating the number of test cases.

Each test case consists of one line containing two squares separated by one space.

A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.

Output

Just output the minimum steps.

下面以两道题作为例子:
第一道题:
象棋马走日:
马的走向总共有8中可能

#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<queue>
using namespace std;
// 8中可能的走向
int moveTo[8][2] = {{1, 2}, {1, -2}, {-1, 2}, {-1, -2},
                    {2, 1}, {2, -1}, {-2, 1}, {-2, -1}};
int chessBoard[8][8];
struct position {
  int x;
  int y;
  int steps;
};
int flag = 1;

bool isValid(int a, int b) {
  if (a >= 0&&a < 8&&b >= 0&&b < 8) return true;
  else return false;
}
bool isEnd(int a, int b, int c, int d) {
  if (a == c && b == d) return true;
  else return false;
}
void bfs(int startX, int startY, int endX, int endY) {
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
    chessBoard[i][j] = 0;
  chessBoard[startX][startY] = 1;
  flag = 1;
  //  用队列实现
  queue<position> chessStep;
  position p;
  p.x = startX;
  p.y = startY;
  p.steps = 0;
  position tem, temp;
  chessStep.push(p);
  while (!chessStep.empty()) {
    tem = chessStep.front();
    chessStep.pop();
    for (int i = 0; i < 8; i++) {
      temp = tem;
      temp.x += moveTo[i][0];
      temp.y += moveTo[i][1];
      if (isValid(temp.x, temp.y)) {
        if (chessBoard[temp.x][temp.y] == 0) {
          temp.steps++;
          if (isEnd(temp.x, temp.y, endX, endY)) {
            cout << temp.steps << endl;
            flag = 0;
            return;
          }
          //  将当前点能走的方向全部入队
          //  通过while循环判断走完第一步后第二步的走向
          //  最先到达end的所通过的路径即为最小
          chessStep.push(temp);
          chessBoard[temp.x][temp.y] = 1;
        }
      }
    }
  }
}
int main() {
  int n;
  char _startx, _endx;
  int _starty, _endy;
  int startx, endx;
  cin >> n;
  while (n--) {
    cin >> _startx >> _starty >> _endx >> _endy;
    _starty -= 1;
    _endy -= 1;
    startx = _startx - 'a';
    endx = _endx - 'a';
    bfs(startx, _starty, endx, _endy);
    if (flag == 1) cout << "0" << endl;
  }
  return 0;
}

注: 每次在一个点上,将该点出队,判断其8个方向是否都能够走,如果能够并且为走过,则将该点入队,判断完8个方向后.即通过while进入下一个循环,即第二步
最先到达end的为最短路径,其steps值即为steps最小数目

2.MAZE(迷宫问题)
You are provided a maze(迷宫), and you need to program to find the least steps to walk from the start to the end.And you can only walk in four directions:up, down,left, right.

There will only be 5 kinds of characters in the maze.The meaning of each is as followed.

“#” is for rock, which you can not walk through.

“S” is for start.

“E” is for end.

“.” is for road.

“!” is for magma(岩浆),which you can not walk through.

Input
n,m represent the maze is a nxm maze.(n rows, m columnsm,0

#####

#S..#

#.!.#

#.#E#

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

int n, m;
int startX;
int startY;
char maze[30][30];
int moveTo[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
//  上下左右四个方向
int flag = 1;
bool isvalidPosition(int n, int m, int indexX, int indexY) {
  if (indexX >= 0 && indexX < n && indexY >= 0 && indexY < m)
  return true;
  else
  return false;
}
bool isValidChar(char ch) {
  if (ch != '!' && ch != '#') return true;
  else return false;
}
struct position {
  int x;
  int y;
  int step;
};

void recursion(int startX, int startY) {
  queue<position> mazeQueue;
  position p;
  p.x = startX;
  p.y = startY;
  p.step = 0;
  mazeQueue.push(p);
  position tem, temp;
  while (mazeQueue.size()) {
     //  越前面元素到达的路径越短,所以到达后直接return
    tem = mazeQueue.front();
    mazeQueue.pop();
    for (int i = 0; i < 4; ++i) {
      //  对于当前的位置,判断其上下左右是否可走,若可走则入队
      temp = tem;
      temp.x += moveTo[i][0];
      temp.y += moveTo[i][1];
      if (isvalidPosition(n, m, temp.x, temp.y)) {
        if (isValidChar(maze[temp.x][temp.y])) {
          temp.step++;
          if (maze[temp.x][temp.y] == 'E') {
            flag = 0;
            cout << temp.step << endl;
            return;
          }
          mazeQueue.push(temp);
          maze[temp.x][temp.y] = '#';
        }
      }
    }
  }
}

int main() {
  cin >> n >> m;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      cin >> maze[i][j];
      if (maze[i][j] == 'S') {
        startX = i;
        startY = j;
      }
    }
  }
  recursion(startX, startY);
  if (flag)
  cout << "-1" << endl;
  return 0;
}

这两道题的整体思路几乎一样,记住:广度优先搜索用队列,即一层一层的搜索,相当于是从左到右建立二叉树,以及一层一层的遍历二叉树.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值