c++,bfs,队列

bfs
bfs=队列
队列的操作

头文件 #include<deque>
声明方法:
1、普通声明

queue<int>q;

2、结构体

struct node
{    
   int x, y;
};
queue<node>q;

操作(假设已经定义队列为q)
q.empty() 如果队列为空返回真
q.pop() 删除对顶元素
q.push() 加入一个元素
q.size() 返回优先队列中拥有的元素个数
q.top() 返回优先队列对顶元素

优先队列
优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大互小的顺序排序。元素的比较规则默认按元素值由大到小排序,可以重载“<”操作符来重新定义比较规则。
声明方式:
1、普通方法:
priority_queue<int>q; //通过操作,按照元素从大到小的顺序出队
priority_queue<int,vector<int>, greater<int> >q; //通过操作,按照元素从小到大的顺序出队
2、自定义优先级:

struct cmp {     
  operator bool ()(int x, int y)     
  {        
     return x > y; // x小的优先级高       //也可以写成其他方式,如: return p[x] > p[y];表示p[i]小的优先级高
  }
};
priority_queue<int, vector<int>, cmp>q;    //定义方法
//其中,第二个参数为容器类型。第三个参数为比较函数。

3、结构体声明方式:

struct node {     
  int x, y;     
  friend bool operator < (node a, node b)     
  {         
    return a.x > b.x;    //结构体中,x小的优先级高     
  }
};
priority_queue<node>q;   //定义方法
//在该结构中,y为值, x为优先级。
//通过自定义operator<操作符来比较元素中的优先级。
//在重载”<”时,最好不要重载”>”,可能会发生编译错误

bfs 由近到远的扩散过程

例题
一个长方形的房间,铺着方砖,每块砖是 #或黑点. 。
一个人站在黑砖上,可以按上、下、左、右方向移动到相邻的砖。
他不能在#上移动,他只能在黑砖上移动。
起点是@,要求:遍历所有黑点。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述
(a)1进队列。当前队列是{1}。
(b)1出队,1的邻居2, 3进队。当前队列{2, 3}。
(可以理解为:从1扩散到2、3。)
©2出队,2的邻居4, 5, 6进队。当前队列{ 3, 4, 5, 6}。
(从2扩散到4、5、6。)
(d)3出队,7, 8进。当前队列{ 4, 5, 6, 7, 8}。
(从3扩散到7、8。)

解决
定义图形和移动方向

int dir[4][2]={  //左上角坐标是(0, 0)。顺时针。
    {-1,0},     //向左。
    {0,-1},     //向上
    {1,0},      //向右
    {0,1}       //向下
};

循环解决

for(int i=0; i<4; i++) { 
                     //按左、上、右、下,4个方向顺时针逐一搜索。
            next.x = start.x + dir[i][0];
            next.y = start.y + dir[i][1];
            if(CHECK(next.x,next.y) && room[next.x][next.y]=='.')  {
                room[next.x][next.y]='#';   
    //进队之后,标记为已经处理过。
                num++;
                q.push(next);
            }
        }

完整代码

#include<bits/stdc++.h>
using namespace std;
char room[23][23];
int dir[4][2] = {
    {-1,0},  //向左。左上角坐标是(0, 0)
    {0,-1},  //向上
    {1,0},   //向右
    {0,1}    //向下
};
int Wx, Hy, num;                 //Wx行,Hy列。用num统计可走的位置有多少
#define CHECK(x, y) (x<Wx && x>=0 && y >=0 && y<Hy) //是否在room里
struct node {int x,y;};
void BFS(int dx,int dy){
    num=1;                         //起点也包含在砖块内
    queue <node> q;              //队列中放坐标点
    node start, next;
    start.x = dx;
    start.y = dy;
    q.push(start);
    while(!q.empty()) {
        start = q.front();
        q.pop();
//cout<<"out"<<start.x<<start.y<<endl;    //打印出队列情况,进行验证
        for(int i=0; i<4; i++) { //按左、上、右、下,4个方向顺时针逐一搜索
            next.x = start.x + dir[i][0];
            next.y = start.y + dir[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 x, y, dx, dy;
    while (cin >> Wx >> Hy) {              //Wx行,Hy列
        if (Wx==0 && Hy==0)       //结束
            break;
        for (y = 0; y < Hy; y++) {         //有Hy列
            for (x = 0; x < Wx; x++) {   //一次读入一行
                cin >> room[x][y];
                if(room[x][y] == '@') {     //读入起点
                    dx = x;
                    dy = y;
                }
            }
        }
        num = 0;
        BFS(dx, dy);
        cout << num << endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值