首页 > 编程语言 >C++U5-04-广度优先搜索1

C++U5-04-广度优先搜索1

时间:2023-11-06 15:44:33浏览次数:32  
标签:MAP 04 vis U5 代码 C++ int && dir

广搜逻辑

 

 广搜代码核心思路

 广搜伪代码

 思维导图

1、[【广搜】走迷宫]

 

求最少需要多少步,考虑使用广搜。从起点开始进行搜索,规则只能向上下左右走动,当搜索到终点时就结束。

广搜的核心思路:
初始化一个队列和数组
将起点入队并标记
当队列不为空且没到终点的时候
取出队首(有需要课进项处理)
队首元素为入过队的邻居入队

【算法分析】
求最少需要多少步,考虑使用广搜。从起点开始进行搜索,规则只能向上下左右走动,当搜索到终点时就结束。

【参考代码】
#include <bits/stdc++.h>
using namespace std;

char MAP[49][49];
bool vis[49][49];
struct node {
    int x, y, step;
}l,r;
int dir[4][2] = { {-1,0} ,{0,1},{1,0},{0,-1} };
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> MAP[i] + 1;
    }
    queue<node> q;
    q.push({ 1,1,1 });
    vis[1][1] = 1;
    while (q.size()) {
        r = q.front();
        q.pop();
        if (r.x == n && r.y == m) {
            cout << r.step;
            break;
        }
        for (int i = 0; i < 4; i++) {
            l.x = r.x + dir[i][0];
            l.y = r.y + dir[i][1];
            l.step = r.step + 1;
            if (l.x >= 1 && l.x <= n && l.y >= 1 && l.y <= m && !vis[l.x][l.y] && MAP[l.x][l.y] == '.') {
                vis[l.x][l.y] = 1;
                q.push(l);
            }
        }
    }
    return 0;
}
点击展开代码

 

2、[【广搜】走出迷宫]

【算法分析】
求最少需要多少步,考虑使用广搜。从起点开始进行搜索,规则只能向上下左右走动,当搜索到终点时就结束。

【参考代码】
#include <bits/stdc++.h>
using namespace std;

char MAP[109][109];
bool vis[109][109];
struct node {
    int x, y, step;
}l,r;
int dir[4][2] = { {-1,0} ,{0,1},{1,0},{0,-1} };
int main() {
    int n, m;
    cin >> n >> m;
    int sx, sy, tx, ty;
    for (int i = 1; i <= n; i++) {
        cin >> MAP[i] + 1;
        for (int j = 1; j <= m; j++) {
            if (MAP[i][j] == 'S') {
                sx = i, sy = j;
            }
            else if (MAP[i][j] == 'T') {
                tx = i, ty = j;
            }
        }
    }
    queue<node> q;
    q.push({ sx,sy,0 });
    vis[sx][sy] = 1;
    while (q.size()) {
        r = q.front();
        q.pop();
        if (r.x == tx && r.y == ty) {
            cout << r.step;
            return 0;
        }
        for (int i = 0; i < 4; i++) {
            l.x = r.x + dir[i][0];
            l.y = r.y + dir[i][1];
            l.step = r.step + 1;
            if (l.x >= 1 && l.x <= n && l.y >= 1 && l.y <= m && !vis[l.x][l.y] && MAP[l.x][l.y] != '#') {
                vis[l.x][l.y] = 1;
                q.push(l);
            }
        }
    }
    cout << -1;
    return 0;
}
点击展开代码

 

3、[【广搜】马的遍历]

 

 

【算法分析】
从马的位置开始广搜,由于求得是最少次数,则每个点只需要访问一次,并且在广搜的过程中记录次数。

【参考代码】
#include <bits/stdc++.h>
using namespace std;

int dis[409][409];
int dir[8][2] = { -2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2 };
struct node {
    int x, y;
}l,r;
int main() {
    memset(dis, -1, sizeof(dis));
    int n, m, x, y;
    cin >> n >> m >> x >> y;
    dis[x][y] = 0;
    queue<node>q;
    q.push({ x,y });
    while (q.size()) {
        r = q.front();
        q.pop();
        for (int i = 0; i < 8; i++) {
            l.x = r.x + dir[i][0];
            l.y = r.y + dir[i][1];
            if (l.x >= 1 && l.x <= n && l.y >= 1 && l.y <= m && dis[l.x][l.y] == -1) {
                dis[l.x][l.y] = dis[r.x][r.y] + 1;
                q.push({ l.x,l.y });
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cout << dis[i][j] << " ";
        }
        cout << '\n';
    }
    return 0;
}

 

4、水洼计数

 

【算法分析】
求一个连通块可以从连通块中的任意一个位置开始,广搜去标记所有与其连通的位置。求图中的连通块个数,可以遍历这个图,碰到一个没有标记的位置且这个位置有水,则从这个位置开始广搜。

【参考代码】
#include <bits/stdc++.h>
using namespace std;

char MAP[119][119];
bool vis[119][119];
int dir[8][2] = { {-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1} };
int n, m;
struct node {
    int x, y;
}l,r;
void bfs(int x, int y) {
    vis[x][y] = 1;
    queue<node> q;
    q.push({ x,y });
    while (q.size()) {
        r = q.front();
        q.pop();
        for (int i = 0; i < 8; i++) {
            l.x = r.x + dir[i][0];
            l.y = r.y + dir[i][1];
            if (l.x >= 1 && l.x <= n && l.y >= 1 && l.y <= m && !vis[l.x][l.y] && MAP[l.x][l.y] == 'W') {
                vis[l.x][l.y] = 1;
                q.push({ l.x,l.y });
            }
        }
    }

}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> MAP[i] + 1;
    }
    int number = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (!vis[i][j] && MAP[i][j] == 'W') {
                number++;
                bfs(i, j);
            }
        }
    }
    cout << number;
    return 0;
}
点击展开代码

 

深搜广搜对比

 

标签:MAP,04,vis,U5,代码,C++,int,&&,dir
From: https://www.cnblogs.com/jayxuan/p/17812857.html

相关文章

  • ERROR 1044 (42000) ERROR 1142 (42000): SELECT command denied to user ''@'localho
    ERROR:Accessdeniedforuser'root'@'localhost'(usingpassword:NO)   发现:   mysql-uroot@localhost-p成功   mysql-uroot-p失败   mysql>SELECTuser,hostFROMmysql.user;   ERROR1142(42000):SELECTcommanddeniedtouser&......
  • 【洛谷 P1046】[NOIP2005 普及组] 陶陶摘苹果 题解(比较)
    [NOIP2005普及组]陶陶摘苹果题目描述陶陶家的院子里有一棵苹果树,每到秋天树上就会结出个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现在已知个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的......
  • C++使用冒泡排序算法对数组进行排序
     #include<iostream>//包含iostream库usingnamespacestd;//使用标准命名空间intmain(){//主函数intarr[]={5,3,2,8,6,7,1,4};//定义并初始化数组intn=sizeof(arr)/sizeof(arr[0]);//计算数组长度//使用冒泡排序算法对数组进......
  • 力扣905 按奇偶排序数组 C++ 双指针+一次遍历
    905.按奇偶排序数组classSolution{public:vector<int>sortArrayByParity(vector<int>&nums){inti=0,j=nums.size()-1;while(i<nums.size()-1&&i<j){while(i<j&&(nums[i]%2==0))i++;......
  • C++_18_多态 - 重写版
     多态:面向对象三大概念:封装、继承、多态!可想而知多态是何等的重要多态的概念以及前提条件:编译期绑定(静态联编):函数入口地址和函数名在编译期间绑定,即编译期间确定函数名和入口地址唯一对应运行期绑定(动态联编):函数入口地址和函数名在编译期间不绑定......
  • C++_17_多继承和虚基类 - 重写版
    多继承单继承:一个派生类只有一个基类,这就是单基类继承,简称“单继承”多继承:一个派生类允许有两个及以上的基类,这就是多基类继承,简称“多继承”单继承中,派生类是对基类的特例化,例如编程类书籍是书籍中的特例。而多继承中,派生类是所有基类的一种组合。在多继承中,派......
  • C++_15_友元函数和友元类 - 重写版
    友元函数和友元类友元函数:通过friend关键字,将不属于当前类的函数在当前类中加以声明,使其成为友元函数,同时该函数能够访问private属性的成员变量。友元类:有有元函数,自然也能有友元类,通过friend关键字,将类A在类B中声明,那么类A会成为类B的友元类注意:1、友......
  • C++_14_常量指针—this指针 - 重写版
    常量指针—this指针this指针:成员函数一般都会拥有一个常量指针(this),指向调用函数的对象,储存的是改对象的首地址(注意:静态成员函数是没有this指针的)//标准写法classbook{public:book(){this->price=0.0;this->title=NULL;}private:doubleprice;char......
  • C++_22_string类型 - 重写版
    string类型·变量定义C++中提供了一个string内建数据类型,它可以替代C语言中的char*数组。使用string数据类型时,需要在程序中包含头文件<string>#include<iostream>#include<string>usingnamespacestd;intmain(){strings1;//......
  • C++_21_重载、重写、重定义 - 重写版
    1、重载同一作用域的同名函数,重复定义;参数格式、参数顺序或者参数类型不同;函数重载和函数的返回值没有任何关系;(const类型的重载本质上是参数类型不同) 2、重写(覆盖)有继承关系子类(派生类)重写父类(基类)的虚函数函数的返回值,函数名字,函数参数,必须和基类中的虚函数一致,主要就是覆盖......