BFS(宽搜)



title: BFS

tags: ACMer

categories: 搜索

thumbnail: https://gss3.bdstatic.com/84oSdTum2Q5BphGlnYG/timg?wapp&quality=80&size=b150_150&subsize=20480&cut_x=0&cut_w=0&cut_y=0&cut_h=0&sec=1369815402&srctrace&di=0af3d14b50480593f373e4a71dda5c97&wh_rate=null&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fpic%2Fitem%2Fca1349540923dd540360d836d209b3de9c824858.jpg


预备知识

队列

特点

  • 先进先出

    理解为单向的管道

    用数组来模拟队列

    头指针往后移一个位置

    虚拟的头尾指针

  • 从队头删除元素
  • 在队尾加入元素

常见操作

  • 判断队列是否为空
  • 查询队列大小

STL队列的基本用法

push和pop,pull

宽度优先搜索

二叉树的层次遍历

想象一下族谱

维护队列

把孩子加到队列里面

最早扩展到的就是最短路径

hdoj 1548 strange lift

什么时候才能进入队列呢?

其实根本不要以为是深搜,我在做递归什么的。其实并没有,我们要做的只是查找到一个节点,我就把这个节点能搜索到的节点进入队列,因为他会进入到最后面,所以根本不用担心

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int MAX = 11000;
struct Node //定义一个结构体关于
{
    int to, step;
} node, nextnode;
int v[MAX], f[MAX]; //v用来标记
int main()
{
    int cas, m, n, i;
    while (scanf("%d", &cas) && cas) //cas表示几楼的数据
    {
        scanf("%d%d", &m, &n);   //m表示起点,n表示终点
        memset(v, 0, sizeof(v)); //数组初始化
        memset(f, 0, sizeof(f));
        for (i = 1; i <= cas; i++)
            scanf("%d", &f[i]); //输入每层的数据
        queue<Node> qu;         //定义队列
        while (!qu.empty())     //清空队列
        {
            qu.pop();
        }
        int t1, t2, flag = 0;
        node.step = 0; //起始点的步数
        node.to = m;
        qu.push(node);  //把结点的情况输入
        v[node.to] = 1; //标记这个点已经走过了
        while (!qu.empty())
        {
            node = qu.front(); //取出首元素
            qu.pop();
            //下面是三种分类讨论:到达终点,向上走,向下走
            if (node.to == n) //如果到达终点
            {
                printf("%d\n", node.step);
                flag = 1;
                break;
            }
            t1 = node.to + f[node.to]; //向上走
            if (t1 <= cas && !v[t1])   //条件的控制
            {

                v[t1] = 1;
                nextnode.to = t1;
                nextnode.step = node.step + 1;
                qu.push(nextnode);
            }
            t1 = node.to - f[node.to]; //向下走
            if (t1 >= 1 && !v[t1])
            {
                v[t1] = 1;
                nextnode.to = t1;
                nextnode.step = node.step + 1;
                qu.push(nextnode);
            }
        }
        if (!flag) //如果走不到
            printf("-1\n");
    }
    return 0;
}

结构体可以理解为一个圈,里面包含了两个信息

hdoj 1495非常可乐

有几个问题解决不了:

  • 怎么判断现在是处于哪个杯子
  • 怎么判断它用了这个杯子

二维就够了,因为加起来是固定的。这里指的是我们自己创建的三维判断矩阵

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int v[5];
int sign[110][110][100];
struct cup //记录遍历中3个水杯容藏可乐情况
{
    int v[5];
    int step;
} temp;

void pour(int a, int b) //倒水函数,把a杯子中的可乐倒到b杯子中
{
    int sum = temp.v[a] + temp.v[b];
    if (sum >= v[b])
        temp.v[b] = v[b];
    else
        temp.v[b] = sum;
    temp.v[a] = sum - temp.v[b];
}

void bfs()
{
    int i, j;
    queue<cup> q;
    cup cnt;
    cnt.v[1] = v[1];
    cnt.v[2] = 0;
    cnt.v[3] = 0;
    cnt.step = 0;
    q.push(cnt);
    memset(sign, 0, sizeof(sign));
    sign[v[1]][0][0] = 1;
    while (!q.empty())
    {
        cnt = q.front();
        q.pop();
        if (cnt.v[1] == cnt.v[3] && cnt.v[2] == 0)
        {
            printf("%d\n", cnt.step);
            return;
        }
        for (i = 1; i < 4; ++i)
        {
            for (j = 1; j < 4; ++j)
            {
                if (i != j) //自己不倒水给自己
                {
                    temp = cnt; //每个水位情况都要把所有操作枚举一遍,所以都要赋值为原始水位情况
                    pour(i, j);
                    if (!sign[temp.v[1]][temp.v[2]][temp.v[3]])
                    {
                        temp.step++;
                        q.push(temp);
                        sign[temp.v[1]][temp.v[2]][temp.v[3]] = 1;
                    }
                }
            }
        }
    }
    printf("NO\n");
}

int main()
{
    while (scanf("%d%d%d", &v[1], &v[2], &v[3]) && v[1] || v[2] || v[3])
    {
        if (v[2] > v[3])
        {
            int t = v[2];
            v[2] = v[3];
            v[3] = t;
        }
        bfs();
    }
    return 0;
}

最先出现的目标是最少的次数

隐式图

hdoj 1372 Knight move(模板题)

组成一个移动的数组,循环八次的数组

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define N 10
using namespace std;
int step[N][N][N][N], visit[N][N];
int dir[][2] = {
    {1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, 1}, {-2, -1}};
struct Node
{
    int x, y, s;
};
int bfs(int sx, int sy, int ex, int ey)
{
    queue<Node> q;
    Node head = {sx, sy, 0};
    q.push(head);
    memset(visit, -1, sizeof(visit));
    visit[sx][sy] = 0;
    while (q.size())
    {
        Node f = q.front();
        q.pop();
        if (f.x == ex && f.y == ey)
            return f.s;
        for (int i = 0; i < 8; i++)
        {
            int dx = dir[i][0] + f.x, dy = dir[i][1] + f.y;
            if (dx >= 0 && dx < 8 && dy >= 0 && dy < 8 && visit[dx][dy])
            {
                visit[dx][dy] = 0;
                Node t = {dx, dy, f.s + 1};
                q.push(t);
            }
        }
    }
}
int main()
{
    cin.sync_with_stdio(false);
    memset(step, -1, sizeof(step));
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
            for (int k = 0; k < 8; k++)
                for (int l = 0; l < 8; l++)
                    if (step[i][j][k][l] != -1)
                        continue;
                    else if (i == k && j == l)
                        step[i][j][k][l] = 0;
                    else
                    {
                        int temp = bfs(i, j, k, l);
                        step[i][j][k][l] = step[k][l][i][j] = temp;
                        step[j][i][l][k] = step[l][k][j][i] = temp;
                    }
    char c1, c2;
    int x1, y2;
    while (cin >> c1 >> x1 >> c2 >> y2)
    {
        printf("To get from %c%d to %c%d takes %d knight moves.\n", c1, x1, c2, y2, step[c1 - ‘a‘][x1 - 1][c2 - ‘a‘][y2 - 1]);
    }
    return 0;
}
#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
typedef pair<int,int> P;
int next1[8][2]={{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
int num[10][10];
int bfs(int sx,int sy,int ex,int ey)
{
    queue<P>q;
    while(!q.empty())
        q.pop();
    q.push(P(sx,sy));
    num[sx][sy]=1;
    while(!q.empty())
    {
        P fx=q.front();
        if(fx.first==ex&&fx.second==ey)
            return num[ex][ey];
        for(int i=0;i<8;i++)
        {
            int nx=fx.first+next1[i][0],ny=fx.second+next1[i][1];
            if(nx>=1&&nx<=8&&ny>=1&&ny<=8&&!num[nx][ny])
            {
                q.push(P(nx,ny));
                num[nx][ny]=num[fx.first][fx.second]+1;
            }
        }
        q.pop();
    }
}
int main()
{
    string ch1,ch2;
    int a,b,c,d;
    while(cin>>ch1>>ch2)//cin遇空格结束输入。。。。。。
    {
        memset(num,0,sizeof(num));
        b=ch1[0]-‘a‘+1;a=ch1[1]-‘0‘;d=ch2[0]-‘a‘+1;c=ch2[1]-‘0‘;
        cout<<"To get from "<<ch1<<" to "<<ch2<<" takes "<<bfs(a,b,c,d)-1<<" knight moves."<<endl;
    }
    return 0;
}
//用pair来做

hdoj 1312 red and black

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 25;
int w, h;
//int ans;
char maze[maxn][maxn];
int start_x, start_y;

int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

struct Node
{
    int x, y;
    int step;
};

bool check(int x,int y)
{
    if(x>=0 && x<w && y>=0 && y<h)
        return true;
    return false;
}

int bfs()
{
    queue<Node> q;
    while (!q.empty())
        q.pop();
    Node now = {start_x,start_y,1};
    int ans =1;
    q.push(now);
    while (!q.empty())
    {
        Node next = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int dx = next.x + dir[i][0];
            int dy = next.y + dir[i][1];
            if(maze[dx][dy]==‘.‘ && check(dx,dy))
            {
                maze[dx][dy] = ‘#‘;
                Node f ={dx,dy,next.step+1};
                ans++;
                q.push(f);
            }
        }
    }
    return ans;
}

int main()
{
    while (~scanf("%d %d", &w, &h) && w+h)
    {
        start_x = 0;
        start_y = 0;
        for (int i = 0; i < h; i++)
        {
            for (int j = 0; j < w; j++)
            {
                cin >> maze[j][i];
                if (maze[j][i] == ‘@‘)
                {
                    start_x = j;
                    start_y = i;
                }
            }
        }
        cout<<bfs()<<endl;
    }
}
  1. 把bfs写成函数
  2. 可以不用写vis数组,如果是迷宫的话可以通过字符的形态来决定有没有走过
  3. 如果数据不一样可能是x,y反了,试着改一改

hdoj 1253胜利大逃亡

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 51;
int status[MAXN][MAXN][MAXN];
int vis[MAXN][MAXN][MAXN];
int dir[6][3] = {{1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}};
struct Ignatius
{
    int x;
    int y;
    int z;
    int step;
};
int main()
{
    int A, B, C, T;
    int K;
    cin >> K;
    while (K--)
    {
        queue<Ignatius> q; //队列清空
        cin >> A >> B >> C >> T;
        Ignatius head = {0, 0, 0, 0};
        //memset(status, 0, sizeof(status));  会在后面输入
        memset(vis, 0, sizeof(vis));
        q.push(head);
        vis[0][0][0] = 1;
        for (int i = 0; i < A; i++)
        {
            for (int j = 0; j < B; j++)
                for (int k = 0; k < C; k++)
                {
                    scanf("%d", &status[i][j][k]);
                }
        }
        //int flag = -1;
        int ans = -1;
        while (!q.empty())
        {
            Ignatius t = q.front();
            q.pop();
            if (t.x == A - 1 && t.y == B - 1 && t.z == C - 1)
            {
                if (t.step <= T)
                {
                    ans = t.step;
                    break;
                }
            }
            for (int i = 0; i < 6; i++)
            {
                int dx = t.x + dir[i][0];
                int dy = t.y + dir[i][1];
                int dz = t.z + dir[i][2];
                if (dx < A && dy < B && dz < C && !vis[dx][dy][dz] && status[dx][dy][dz] != 1 && dx >= 0 && dy >= 0 && dz >= 0)
                {
                    vis[dx][dy][dz] = 1;
                    Ignatius f = {dx, dy, dz, t.step + 1}; // 直接在里面加步数
                    q.push(f);
                }
            }
            //怎么判断是找不到路还是时间不够
        }
        cout << ans << endl; //省去了flag的  自己引用t.step的话没有定义
    }

    return 0;
}

2717 catch that cow

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 100010;
int vis[maxn];

int main()
{
    int n, k;
    while (~scanf("%d %d", &n, &k))
    {
        memset(vis, 0, sizeof(vis));
        queue<int> q;
        while (!q.empty())
            q.pop();
        q.push(n);
        vis[n] = 0;
        while (!q.empty())
        {
            int temp = q.front();
            if (temp == k)
                break;
            if (temp + 1 <= 100000 && !vis[temp + 1] && temp + 1 >= 0)
            {
                q.push(temp + 1);
                vis[temp + 1] = vis[temp] + 1;
                //ans++;  步数在里面加,因为如果是在外面的话算的是提取队列的次数
            }
            if (temp - 1 >= 0 && !vis[temp - 1] && temp - 1 <= 100000)
            {
                q.push(temp - 1);
                vis[temp - 1] = vis[temp] + 1;
            }
            if (temp * 2 <= 100000 && !vis[temp * 2] && temp * 2 >= 0)
            {
                q.push(temp * 2);
                vis[temp * 2] = vis[temp] + 1;
            }
            q.pop();
        }
        cout << vis[k] << endl;
    }
    return 0;
}

  1. 每次都要清空队列,也就是while不空,就一直pop
  2. 有些东西可以整合到一起,比如说进队列的过程,可以一起放到循环里面来
  3. 判断是否满足条件要注意在哪个地方判断,是否会多走一次
  4. 要包含步数的话,可以写在结构体里面或者用vis数组

hdoj prime path

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
char a[5];
char b[5];
bool vis[12][12][12][12];
bool Is_prime[10005];
int ans;

struct Num
{
    int num[4]; // 一开始想构造一个函数的
    int step;
};

void bfs()
{
    memset(vis,0,sizeof(vis));
    queue<Num> q;
    while (!q.empty())
        q.pop();
    Num start, des;
    ans = 0;
    for (int i = 0; i < 4; i++)
    {
        start.num[i] = a[i] - ‘0‘;
        des.num[i] = b[i] - ‘0‘;
    }
    start.step = 0;
    vis[start.num[0]][start.num[1]][start.num[2]][start.num[3]] = 1;
    q.push(start);
    while (!q.empty())
    {
        Num now = q.front();
        q.pop();
        if (now.num[0] == des.num[0] && now.num[1] == des.num[1] && now.num[2] == des.num[2] && now.num[3] == des.num[3])
        {
            ans = now.step;
            return;
        }
        for (int i = 0; i < 4; i++)
        {
            if (i == 0)
            {
                for (int j = 1; j <= 9; j++)
                {
                    int temp = j * 1000 + now.num[1] * 100 + now.num[2] * 10 + now.num[3];
                    if (!vis[j][now.num[1]][now.num[2]][now.num[3]] && !Is_prime[temp])
                    {
                        Num f; //= {j,now.num[1],now.num[1],now.num[1]}
                        f.num[0] = j;
                        f.num[1] = now.num[1];
                        f.num[2] = now.num[2];
                        f.num[3] = now.num[3];
                        f.step = now.step + 1;
                        vis[j][now.num[1]][now.num[2]][now.num[3]] = 1;
                        q.push(f);
                    }
                }
            }
            if (i == 1)
            {
                for (int j = 0; j <= 9; j++)
                {
                    int temp = now.num[0] * 1000 + j * 100 + now.num[2] * 10 + now.num[3];
                    if (!vis[now.num[0]][j][now.num[2]][now.num[3]] && !Is_prime[temp])
                    {
                        Num f; //= {j,now.num[1],now.num[1],now.num[1]}
                        f.num[0] = now.num[0];
                        f.num[1] = j;
                        f.num[2] = now.num[2];
                        f.num[3] = now.num[3];
                        f.step = now.step + 1;
                        vis[now.num[0]][j][now.num[2]][now.num[3]] = 1;
                        q.push(f);
                    }
                }
            }
            if (i == 2)
            {
                for (int j = 0; j <= 9; j++)
                {
                    int temp = now.num[0] * 1000 + now.num[1] * 100 + j * 10 + now.num[3];
                    if (!vis[now.num[0]][now.num[1]][j][now.num[3]] && !Is_prime[temp])
                    {
                        Num f; //= {j,now.num[1],now.num[1],now.num[1]}
                        f.num[0] = now.num[0];
                        f.num[1] = now.num[1];
                        f.num[2] = j;
                        f.num[3] = now.num[3];
                        f.step = now.step + 1;
                        vis[now.num[0]][now.num[1]][j][now.num[3]] = 1;
                        q.push(f);
                    }
                }
            }
            if (i == 3)
            {
                for (int j = 0; j <= 9; j++)
                {
                    int temp = now.num[0] * 1000 + now.num[1] * 100 + now.num[2] * 10 + j;
                    if (!vis[now.num[0]][now.num[1]][now.num[2]][j] && !Is_prime[temp])
                    {
                        Num f; //= {j,now.num[1],now.num[1],now.num[1]}
                        f.num[0] = now.num[0];
                        f.num[1] = now.num[1];
                        f.num[2] = now.num[2];
                        f.num[3] = j;
                        f.step = now.step + 1;
                        vis[now.num[0]][now.num[1]][now.num[2]][j] = 1;
                        q.push(f);
                    }
                }
            }
        }
    }
}

int main()
{
    int t;
    for (int i = 2; i * i <= 10000; i++) // true为非素数
    {
        if (!Is_prime[i])
            for (int j = i * i; j <= 10000; j += i)
            {
                Is_prime[j] = true;
            }
    }
    cin >> t;
    while (t--)
    {
        scanf("%s %s", a, b);
        bfs();
        cout<<ans<<endl;
    }
}

ACwing 844走迷宫

自己写的代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, pair<int, int>> PII;
const int maxn = 100 + 10;
int n, m;
int cnt; // 也要加到结构体里面去,因为这样才能代表走到那个位置用了多少步
int maze[maxn][maxn];
bool st[maxn][maxn];
int dir[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

/*
还可以使用
pair<pair<int, int>, int> PII;
存数据进去的时候注意{{}, }
*/
struct Cor
{
    int x;
    int y;
    int step;
}cor[maxn];
queue<Cor> q;

bool check(int i, int j)
{
    if(i >= 1 && i <= n && j >= 1 && j <= m) return true;
    return false;
}

int bfs(int start_x, int start_y, int end_x, int end_y)
{
    st[start_x][start_y] = 1;
    q.push({start_x, start_y});
    while (!q.empty())
    {
        //PII now = q.front();
        Cor now = q.front();
        q.pop();
        cnt ++ ;
        int x = now.x;
        int y = now.y;
        int step = now.step;
        if (x == end_x && y == end_y)
        {
            return step;
        }
        for (int i = 0; i < 4; i ++ )
        {
            int dx = x + dir[i][0];
            int dy = y + dir[i][1];
            if(!st[dx][dy] && maze[dx][dy] != 1 && check(dx, dy))
            {
                st[dx][dy] = 1;
                q.push({dx, dy, step + 1});
			   // 不支持这个语法的话,就创建一个结构体然后把结构体push进去
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j <= m; j ++ )
        {
            scanf("%d", &maze[i][j]);
        }
    }
    cout << bfs(1, 1, n, m) << endl;
}

y总代码

#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> PII;

const int N = 110;

int n, m;
int g[N][N], d[N][N];

int bfs()
{
    queue<PII> q;

    memset(d, -1, sizeof d);
    d[0][0] = 0;
    q.push({0, 0});

    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    while (q.size())
    {
        auto t = q.front(); // 自动得到t的类型
        q.pop();

        for (int i = 0; i < 4; i ++ )
        {
            int x = t.first + dx[i], y = t.second + dy[i];

            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
            {
                d[x][y] = d[t.first][t.second] + 1;
                q.push({x, y});
            }
        }
    }

    return d[n - 1][m - 1];
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            cin >> g[i][j];

    cout << bfs() << endl;

    return 0;
}

BFS总结

生成的状态放到数组里面

优先队列priority queue

hdoj 1242 rescue

优先队列方法

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <queue>
#define MAXN 10000
using namespace std;
char map[1100][1100];
int vis[1100][1100];
int n, m;
int mi;
int sx, sy, ex, ey;
int dx[5] = {1, -1, 0, 0};
int dy[5] = {0, 0, 1, -1};
struct st
{
    int x;
    int y;
    int time;
    bool friend operator<(st a, st b)
    {
        return a.time > b.time;
    }
};
bool judge(st a)
{
    if (a.x < 0 || a.x >= n || a.y < 0 || a.y >= m || map[a.x][a.y] == ‘#‘ || vis[a.x][a.y])
        return false;
    return true;
}
int bfs(int x, int y)
{
    priority_queue<st> q;
    while (!q.empty())
        q.pop();
    st a;
    a.x = x;
    a.y = y;
    a.time = 0;
    vis[x][y] = 1;
    q.push(a);
    while (!q.empty())
    {
        st b = q.top();
        q.pop();
        if (map[b.x][b.y] == ‘a‘)
            return b.time;
        for (int i = 0; i < 4; i++)
        {
            st end;
            end.x = b.x + dx[i];
            end.y = b.y + dy[i];
            end.time = b.time;
            if (judge(end))
            {
                if (map[end.x][end.y] == ‘x‘)
                    end.time++;
                end.time++;
                q.push(end);
                vis[end.x][end.y] = 1;
            }
        }
    }
    return 0;
}
int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        memset(map, 0, sizeof(map));
        for (int i = 0; i < n; i++)
        {
            scanf("%s", map[i]);
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {
                if (map[i][j] == ‘r‘)
                {
                    memset(vis, 0, sizeof(vis));
                    int ans = bfs(i, j);
                    if (ans < mi)
                        mi = ans;
                }
            }
        memset(vis, 0, sizeof(vis));
        if (mi == 0)
            printf("Poor ANGEL has to stay in the prison all his life.\n");
        else
            printf("%d\n", mi);
    }
    return 0;
}
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <queue>
#define MAXN 10000
using namespace std;
char map[1100][1100];
int vis[1100][1100];
int n, m;

int sx, sy, ex, ey;
int dx[5] = {1, -1, 0, 0};
int dy[5] = {0, 0, 1, -1};
struct st
{
    int x;
    int y;
    int time;
    bool friend operator<(st a, st b)
    {
        return a.time > b.time;
    }
};
bool judge(st a)
{
    if (a.x < 0 || a.x >= n || a.y < 0 || a.y >= m || map[a.x][a.y] == ‘#‘ || vis[a.x][a.y])
        return false;
    return true;
}
int bfs(int x, int y)
{
    priority_queue<st> q;
    while (!q.empty())
        q.pop();
    st a;
    a.x = x;
    a.y = y;
    a.time = 0;
    vis[x][y] = 1;
    q.push(a);
    while (!q.empty())
    {
        st b = q.top();
        q.pop();
        if (map[b.x][b.y] == ‘a‘)
            return b.time;
        for (int i = 0; i < 4; i++)
        {
            st end;
            end.x = b.x + dx[i];
            end.y = b.y + dy[i];
            end.time = b.time;
            if (judge(end))
            {
                if (map[end.x][end.y] == ‘x‘)
                    end.time++;
                end.time++;
                q.push(end);
                vis[end.x][end.y] = 1;
            }
        }
    }
    return 9999999;
}
int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        int mi=9999999;
        memset(map, 0, sizeof(map));
        for (int i = 0; i < n; i++)
        {
            scanf("%s", map[i]);
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {
                if (map[i][j] == ‘r‘)
                {
                    memset(vis, 0, sizeof(vis));
                    int ans = bfs(i, j);
                    if (ans < mi)
                        mi = ans;
                }
            }
        memset(vis, 0, sizeof(vis));
        if (mi == 9999999)
            printf("Poor ANGEL has to stay in the prison all his life.\n");
        else
            printf("%d\n", mi);
    }
    return 0;
}

老刘说了一句话,你们在掉了几百块钱很伤心,但是很多人不来我的课。其实我讲课几百块钱一小时。你想交钱我还不一定教

定义好一类规则就行了,长得最帅的出去,全部都出去了

优先队列其实是一个大顶堆,什么是堆呢?堆就是一个拟满二叉树,最后一层的上面全是满的。最后一层全部靠左

前缀编码里面没有前缀

我去找老师---学生找到我

在一个命名空间可以少打两次

greater表示小顶堆

硬着头皮写,问同学

不理解不要写上去,为每一句话负责

收获信息港

剪枝优化,动态规划和搜索都是最优的子问题

https://www.cnblogs.com/ECJTUACM-873284962/p/6750320.html

hdoj 1053 https://blog.csdn.net/dzyhenry/article/details/8887956

1242 https://blog.csdn.net/sdc1992/article/details/7875813

2717 https://blog.csdn.net/rnzhiw/article/details/81414837

1612 https://blog.csdn.net/simoncoder/article/details/44803559

原文地址:https://www.cnblogs.com/WalterJ726/p/12685416.html

时间: 2024-10-10 20:02:25

BFS(宽搜)的相关文章

POJ 2251宽搜、

因为这个题做了两次犯了两次不同的错误. 第一次用的dfs死活都超时 第二次把定义队列定义在了全局变量的位置,导致连WA了几次.最后找到原因的我真的想一巴掌拍死自己 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 const int qq=40; 6 int vis[qq][qq][qq]; 7 char map[qq][qq][qq]; 8 int tz,

【NOIP2016提高组】愤怒的小鸟(状压宽搜)

题目描述 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行轨迹经过了(xi,yi),那么第i只小猪就会被消灭掉,同时小鸟将会沿着原先

poj2243Knight Moves宽搜

#include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<set> us

【csp模拟赛5】加减法--宽搜维护联通快

题目大意: 一开始想用并查集,发现很难维护联通块的代表元素,所以用了宽搜,开数组会炸,所以开一个优先队列维护,每扫完一个联通块,统计答案,清空优先队列,!!千万记住注意数组的大小!!! 代码: #include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<cstring> #include<queue> #define int lo

宽搜--knight moves hdu1372

写出来之后觉得是一道简单的宽搜题,但是之前写的时候遇到很多细节处理的小问题.刚刚开始,还需要更加努力. 首先是题目意思,骑士移动原来是走日字,智商捉急. 其次是方向处理问题,之前一直没转过弯.普遍方向表达有两种 第一种: int h[8][2]={{-2,-1},{-2,1},{-1,2},{-1,-2},{1,-2},{1,2},{2,-1},{2,1}}; for(int i=0;i<8;i++){ next.a=head.a+h[i][0]; next.b=head.b+h[i][1];

HDU 5012 bfs暴搜

Dice Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 243    Accepted Submission(s): 135 Problem Description There are 2 special dices on the table. On each face of the dice, a distinct number wa

【图论】【宽搜】【染色】NCPC 2014 A Ades

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1787 题目大意: N个点M条无向边(N,M<=200000),一个节点只能有一个标记.每条边有一个值{0,1或2}表示这条边连接的两个节点拥有的标记之和.问只要要多少个标记才能满足,无解impossible. 题目思路: [图论][宽搜] 因为每个点只能有或没有标记.所以可以枚举每个联通块的其中一个点有还是没有标记,用这个点去拓展这个点的联通块并01染色(这个点所能到达的所有点) 初

poj1399 hoj1037 Direct Visibility 题解 (宽搜)

http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minecraft方块地图上(由很多1*1*1的方块搭起来的地图,最高5000),其中两块分别有高0.5米的激光塔,有一个高0.5米的机器人要从其中一个激光塔走到另一个.要求只能走相邻4个方向,每次不能爬上超过1格或跳下超过3格(咦,好像真的很像minecraft),要求每走到一个格子,机器人站在在这个格子的

2014牡丹江网络预选赛F题(隐式图BFS暴搜)zoj3814

Sawtooth Puzzle Time Limit: 10 Seconds      Memory Limit: 65536 KB Recently, you found an interesting game called Sawtooth Puzzle. This is a single-player game played on a grid with 3 x 3 cells. Each cell contains a part of an image. Besides, each ed