万能的搜索之BFS

简介: 万能的搜索之BFS

1.拯救小哈之BFS

具体题目描述 点击这里

参考代码
#include<iostream>
#include<queue>
using namespace std;
struct node {
  int x;
  int y;
  int f;
  int s;//步数
};
int NEXT[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
int n, m, startx, starty, p, q, tx, ty, flag;
queue<node> que;
int main()
{
  int a[51][51] = { 0 }, book[51][51] = { 0 };
  cin >> n >> m;
  for (int i = 1; i <= n; i++)
  {
    for (int j = 1; j <= m; j++) {
      cin >> a[i][j];
    }
  }
  cin >> startx >> starty >> p >> q;
  node nd;
  nd.x = startx;
  nd.y = starty;
  nd.f = 0;
  nd.s = 0;
  que.push(nd);
  book[startx][starty] = 1;
  flag = 0;//标记是否到达目标点
  //当队列不为空的时候循环
  while (!que.empty()) {
    //四个方向
    node n1 = que.front();
    for (int i = 0; i <= 3; i++) {
      tx = n1.x + NEXT[i][0];
      ty = n1.y + NEXT[i][1];
      //是否越界
      if (tx < 1 || tx > n || ty <1 || ty > m) {
        continue;
      }
      if (a[tx][ty] == 0 && book[tx][ty] == 0) {
        book[tx][ty] = 1;
        node n2;
        n2.x = tx;
        n2.y = ty;
        n2.f = n1.f;
        n2.s = n1.s + 1;
        que.push(n2);
      }
      //如果到目标点了,停止扩展,结束循环
      if (tx == p && ty == q) {
        flag = 1;
        break;
      }
    }
    if (flag) {
      break;
    }
    //当前点扩展结束,弹出改点.
    que.pop();
  }
  if (que.size() > 0) {
    cout << que.back().s << endl;
  }
  return 0;
}

2.炸弹人

游戏简述

通过放置炸弹的方法来消灭敌人,炸弹只能放置在空地上,炸弹可以向上下左右四个方向炸开,碰到敌人可以消灭,但是碰到墙则停止这个炸弹在这个方向上的威力。

20210415094901419.png

现在有个特殊的关卡,只有一枚炸弹(炸弹威力大杀伤距离足够强威力足够大),请问这个炸弹放置在地图上的哪个空位上,能够消灭最多数量的敌人。

20210415094947539.png

先将地图模型化,把墙用符号“#”表示,敌人用大写字母G表示,空地用英文点号“.”表示,整张地图可以抽象成一个二维数组。接下来我们使用BFS解决.

参考代码
#include<iostream>
#include<queue>
using namespace std;
struct node {
  int x;
  int y;//横纵坐标
};
char a[25][25];//用来存储地图
int sum1, x, y,max1,mx,my,n,m,startx,starty,tx,ty;
queue<node> que;
int book[25][25];//定义一个标记
int NEXT[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };//方向数组
int getnum(int i, int j) {
  int sum;
  sum = 0;//用于计数
  x = i;
  y = j;
  //向上统计  可以消灭的敌人
  while (a[x][y] != '#') {//判断该点是不是墙
    if (a[x][y] == 'G') {
      sum++;
    }
    x--;
  }
  //向下统计
  x = i;
  y = j;
  while (a[x][y] != '#') {
    if (a[x][y] == 'G') {
      sum++;
    }
    x++;
  }
  //向左统计
  x = i;
  y = j;
  while (a[x][y]!='#')
  {
    if (a[x][y] == 'G') {
      sum++;
    }
    y--;
  }
  //向右统计
  x = i;
  y = j;
  while (a[x][y] != '#')
  {
    if (a[x][y] == 'G') {
      sum++;
    }
    y++;
  }
  return sum;
}
int main() {
  cin >> n >> m >> startx >> starty;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  //队列初始化
  node nd;
  nd.x = startx;
  nd.y = starty;
  que.push(nd);
  max1 = getnum(startx, starty);
  mx = startx;
  my = starty;
  //队列不为空时进行循环
  while (!que.empty()) {
    //枚举四个方向
    node nd2 = que.front();
    for (int i = 0; i <= 3; i++) {
      sum1 = 0;
      tx = nd2.x + NEXT[i][0];
      ty = nd2.y + NEXT[i][1];
      if (tx < 0 || tx > n - 1 || ty < 0 || ty > m - 1) {//判断是否越界
        continue;
      }
      if (a[tx][ty] == '.' && book[tx][ty] == 0) {
        book[tx][ty] = 1;
        node nd3;
        nd3.x = tx;
        nd3.y = ty;
        que.push(nd3);
        sum1 = getnum(tx, ty);
        if (sum1 > max1) {
          max1 = sum1;
          mx = tx;
          my = ty;
          //cout << "哈哈哈" << max1 << endl;
        }
      }
    }
    que.pop();
  }
  cout << "将炸弹放在:" << mx <<" "<< my << "处,最多可以消灭的敌人是" << max1 << endl;
  return 0;
}
/*
13 13 3 3
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G...G.....#
#G#.#G###.#G#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#GG.GGG#G.GG#
#############
*/

运行结果

20210415095716187.png

可以看出BFS的核心是:搜索所有的空白快,完毕后输出最小的即可.

该题也可使用DFS进行解决

参考代码2
#include<iostream>
using namespace std;
char a[25][25];//用来存储地图
int sum1, x, y, max1, mx, my, n, m, startx, starty, tx, ty;
int book[25][25];//定义一个标记
int NEXT[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };//方向数组
int getnum(int i, int j) {
  int sum;
  sum = 0;//用于计数
  x = i;
  y = j;
  //向上统计可以消灭的敌人
  while (a[x][y] != '#') {//判断的点是不是墙
    if (a[x][y] == 'G') {
      sum++;
    }
    x--;
  }
  //向下统计
  x = i;
  y = j;
  while (a[x][y] != '#') {
    if (a[x][y] == 'G') {
      sum++;
    }
    x++;
  }
  //向左统计
  x = i;
  y = j;
  while (a[x][y] != '#')
  {
    if (a[x][y] == 'G') {
      sum++;
    }
    y--;
  }
  //向右统计
  x = i;
  y = j;
  while (a[x][y] != '#')
  {
    if (a[x][y] == 'G') {
      sum++;
    }
    y++;
  }
  return sum;
}
void dfs(int x, int y) {
  sum1 = getnum(x, y);
  if (sum1 > max1) {
    max1 = sum1;
    mx = x;
    my = y;
  }
  for (int i = 0; i <= 3; i++) {
    sum1 = 0;
    tx = x+ NEXT[i][0];
    ty = y + NEXT[i][1];
    if (tx < 0 || tx > n - 1 || ty < 0 || ty > m - 1) {
      continue;
    }
    //判断是否走过
    if (a[tx][ty] == '.' && book[tx][ty] == 0) {
      book[tx][ty] = 1;
      dfs(tx, ty);
    }
  }
  return;
}
int main() {
  cin >> n >> m >> startx >> starty;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  book[startx][starty] = 1;
  max1 = getnum(startx, starty);
  mx = startx;
  my = starty;
  dfs(startx, starty);
  cout << "将炸弹放在:" << mx << " " << my << "处,最多可以消灭的敌人是" << max1 << endl;
  return 0;
}

DFS解决的话,在于只要遍历过就行,无需回溯.


3.宝岛冒险

小哼通过秘密方法得到了一张不完整的钓鱼岛航拍地图。钓鱼岛由一个主岛和一些附属岛屿组成,小哼决定去钓鱼岛冒险。下面这个 10 * 10 的二维码矩阵就是钓鱼岛的航拍地图。图中数字代表海拔,0 表示海洋,1~9 表示陆地。小哼的飞机将会在(6,8)处,现在需要计算出小哼落地所在岛屿的面积(即有多少个格子)。


1 2 1 0 0 0 0 0 2 3

3 0 2 0 1 2 1 0 1 2

4 0 1 0 1 2 3 2 0 1

3 2 0 0 0 1 2 4 0 0

0 0 0 0 0 0 1 5 3 0

0 1 2 1 0 1 5 4 3 0

0 1 2 3 1 3 6 2 1 0

0 0 3 4 8 9 7 5 0 0

0 0 0 3 7 8 6 0 1 2

0 0 0 0 0 0 0 0 1 0


参考代码1–DFS

#include<iostream>
using namespace std;
int startx, starty,tx,ty,sum;
int NEXT[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
int book[13][13], map[13][13],total= 1;
//深搜  
void dfs(int x, int y) {
  for (int i = 0; i < 4; i++) {
    tx = x + NEXT[i][0];
    ty = y + NEXT[i][1];
    //判断是否越界
    if (tx < 1 || tx > 10 || ty < 1 || ty > 10) {
      continue;
    }
    //判断是否是陆地
    if (map[tx][ty] >= 1 && map[tx][ty] <= 9 && !book[tx][ty]) {
      book[tx][ty] = 1;
      total++;
      dfs(tx, ty);
    }
  }
}
int main()
{
  for (int i = 1; i <= 10; i++) {
    for (int j = 1; j <= 10; j++) {
      cin >> map[i][j];
    }
  }
  book[6][8] = 1;
  dfs(6, 8);
  cout << total << endl;
  return 0;
}

image.png


参考代码2—BFS

#include<iostream>
#include<queue>
using namespace std;
struct node {
  int X;
  int Y;
};
queue<node> que;
int startx, starty,tx,ty,sum;
int NEXT[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
int book[13][13], map[13][13],total= 1;
void bfs(int x, int y) {
  node nd;
  nd.X = x;
  nd.Y = y;
  que.push(nd);
  while (!que.empty()) {
    node nd2;
    nd2 = que.front();
    for (int i = 0; i <= 3; i++) {
      tx = nd2.X + NEXT[i][0];
      ty = nd2.Y + NEXT[i][1];
      //判断是否越界
      if (tx < 1 || tx > 10 || ty < 1 || ty > 10) {
        continue;
      }
      if (map[tx][ty] >= 1 && map[tx][ty] <= 9 && !book[tx][ty]) {
        node nd3;
        nd3.X = tx;
        nd3.Y = ty;
        que.push(nd3);
        book[tx][ty] = 1;
        total++;
      }
    }
    que.pop();
  }
}
int main()
{
  for (int i = 1; i <= 10; i++) {
    for (int j = 1; j <= 10; j++) {
      cin >> map[i][j];
    }
  }
  book[6][8] = 1;
  bfs(6, 8);
  cout << total << endl;
  return 0;
}
/*
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0
  38
*/


相关文章
【C++】递归,搜索与回溯算法入门介绍和专题一讲解
【C++】递归,搜索与回溯算法入门介绍和专题一讲解
|
3月前
|
算法
【算法】递归、搜索与回溯——简介
【算法】递归、搜索与回溯——简介
|
5月前
|
算法
第4章 万能的搜索
第4章 万能的搜索
|
6月前
深度优化搜索,字典树
深度优化搜索,字典树
56 0
|
机器学习/深度学习 算法
搜索与图论 - 搜索与图在算法中的应用【中】
搜索与图论 - 搜索与图在算法中的应用【中】
|
存储 机器学习/深度学习 算法
搜索与图论 - 搜索与图在算法中的应用【上】
搜索与图论 - 搜索与图在算法中的应用【上】
|
算法 Java Python
【算法题解】 Day30 搜索与回溯
今天的算法是 「搜索与回溯」 相关,“算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,以实战习题的形式理解算法,使用算法。”
106 0
|
定位技术
|
算法 机器人 Java
【算法题解】 Day29 搜索与回溯
今天的算法是 「搜索与回溯」 相关,“算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,以实战习题的形式理解算法,使用算法。”
97 0