广度优先搜索(BFS)

广度优先搜索会优先考虑每种状态和初始状态的距离(与初始状态越接近的情况就会越优先考虑),具体一点就是:每个时刻要做的事情就是从上一个时刻每个状态扩展出新的状态。

广度优先搜索使用队列实现:先将初始状态加入到空的队列当中,然后每次取出队首,找出队首所能转移到的状态,再将其插入队列;如此反复,直到队列为空。这样就能保证一个状态在被访问的时候一定是采用最短的路径。

广度优先搜索的一般形式如下:

Q.push(初始状态);//将初始状态入队
while(!Q.empty())
{
    State u = Q.front();//取出队首
    Q.pop();//队首出队
    for(枚举所有可扩展的状态)//找到u的所有可达状态v
    {
        if(状态合法)//v需要满足某些条件,如未访问过、未在队内等
        {
            Q.push(v);//入队(同时可能需要维护某些必要信息)
        }
    }
}

 洛谷 P1443 马的遍历

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 410
typedef struct point{ //一个结构体储存x,y两个坐标
    int x,y;
}point;
queue<point> Q;//队列
int ans[maxn][maxn];//记录答案,-1代表未访问过
int direction[8][2] = {{2,-1},{2,1},{1,-2},{1,2},
                    {-1,-2},{-1,2},{-2,-1},{-2,1}};//马能走的八个方向
int main()
{
    int n,m,sx,sy;
    memset(ans,-1,sizeof(ans));
    cin >> n >> m >> sx >> sy;
    point tmp;
    tmp.x = sx;
    tmp.y = sy;
    Q.push(tmp);//将起始点入队
    ans[sx][sy] = 0;//记录起始点答案
    while(!Q.empty())
    {
        tmp = Q.front();//队首出列
        int popx = tmp.x;
        int popy = tmp.y;
        int d = ans[popx][popy];//取出队首答案
        Q.pop();//出队
        for(int i = 0 ; i < 8 ; i++)
        {
            int cx = popx + direction[i][0]; //拓展点的x值
            int cy = popy + direction[i][1]; //拓展点的y值
            if( cx >= 1 && cx <= n && cy >= 1 && cy <= m && ans[cx][cy] == -1)
            {
                ans[cx][cy] = d + 1;//记录答案,是上一步多走一步的结果
                tmp = {cx,cy};
                Q.push(tmp);//满足条件,入队
            }
        }
    }
    for(int i = 1 ; i <= n ; i++)
    {
        for(int j = 1 ; j <= m ; j++)
        {
            printf("%-5d",ans[i][j]);
        }
        printf("\n");
    }
    return 0;
}

洛谷 P1135 奇怪的电梯

#include<iostream>
#include<queue>
using namespace std;
typedef struct node{
    int floor;//层数
    int time;//按钮次数
}node;

queue<node> Q;//队列
int n,a,b;
int k[1000];//记录每层可以跳跃几层
int vis[1000];//记录是否被访问过
int main()
{
    cin >> n >> a >> b;
    for( int i = 1 ; i <= n ; i++)
    {
        cin >> k[i];
    }
    node tmp = {a,0};
    Q.push(tmp);//将起始点插入队列
    vis[a] = 1;//记录初始楼层已经被访问过
    node now;//最新到达的楼层
    while(!Q.empty())
    {
        now = Q.front();
        Q.pop();
        if(now.floor == b) 
        break; //找到目标解
        for( int sign = -1 ; sign <= 1 ; sign += 2 )//上下两个方向
        {
            int curFloor = now.floor + k[now.floor] * sign;//搜索目标的楼层
            if( curFloor >= 1 && curFloor <= n && vis[curFloor] == 0)//如果按按钮能够到达该楼层有效且未被访问过
            {
                tmp = {curFloor,now.time + 1};
                Q.push(tmp);//入队
                vis[curFloor] = 1; //记录该楼层已被访问过了
            }
        }
    }
    if(now.floor == b)
    {
        cout << now.time << endl;
    }
    else
    {
        cout << -1 << endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值