Algoritmo - bfs (primera búsqueda en amplitud)

Introducción
El algoritmo de búsqueda en amplitud (también llamado búsqueda en amplitud) es uno de los algoritmos de búsqueda de gráficos más simples y también es el prototipo de muchos algoritmos de gráficos importantes. Su alias también se llama BFS, que es un método de búsqueda ciega cuyo propósito es expandir y verificar sistemáticamente todos los nodos en el gráfico para encontrar resultados. En otras palabras, no considera las posibles ubicaciones de los resultados y busca minuciosamente en todo el gráfico hasta encontrar los resultados.

El problema más clásico de BFS es el problema del laberinto y el problema del camino más corto.

给定一个 n×m 的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0 表示可以走的路,1 表示不可
通过的墙壁。

最初,有一个人位于左上角 (1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。

请问,该人从左上角移动至右下角 (n,m) 处,至少需要移动多少次。

数据保证 (1,1) 处和 (n,m) 处的数字为 0,且一定至少存在一条通路。

输入格式
第一行包含两个整数 n 和 m。

接下来 n 行,每行包含 m 个整数(0 或 1),表示完整的二维数组迷宫。

输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。

数据范围
1≤n,m≤100
输入样例:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例:
8

Código:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int s[N][N],n,m,g[N][N];
int bfs()
{
    
    
    queue<PII> q;
    memset(g, -1, sizeof g);
    q.push({
    
    0,0});
    g[0][0]=0;
    int dx[4] = {
    
    -1, 0, 1, 0}, dy[4] = {
    
    0, 1, 0, -1};
    while(q.size())
    {
    
    
        auto t=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
    
    
            int a=t.first+dx[i],b=t.second+dy[i];
            if(a>=0&&a<n&&b>=0&&b<m&&g[a][b]==-1&&s[a][b]==0)
            {
    
    
                g[a][b]=g[t.first][t.second]+1;
                q.push({
    
    a,b});
            }
        }
    }
    return g[n-1][m-1];
}
int main()
{
    
    cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>s[i][j];
cout<<bfs()<<endl;
}

La estructura del código es básicamente utilizar las características de la cola para mover el punto actual y continuar realizando el bucle cuando la cola no esté vacía. Cuando se llegue al punto de destino no se añadirán nuevos elementos, si esto continúa, el primero en llegar al punto de destino será el que tenga la distancia más corta.

También hay un número ocho clásico.

在一个 3×3 的网格中,1∼8 这 8 个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。

例如:

1 2 3
x 4 6
7 5 8
在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 x
例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
x 4 6   4 x 6   4 5 6   4 5 6
7 5 8   7 5 8   7 x 8   7 8 x
现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式
输入占一行,将 3×3 的初始网格描绘出来。

例如,如果初始网格如下所示:

1 2 3 
x 4 6 
7 5 8 
则输入为:1 2 3 x 4 6 7 5 8

输出格式
输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出 −1。

输入样例:
2  3  4  1  5  x  7  6  8
输出样例
19

Código:

#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <queue>

using namespace std;

int bfs(string state)
{
    
    
    queue<string> q;
    unordered_map<string, int> d;

    q.push(state);
    d[state] = 0;

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

    string end = "12345678x";
    while (q.size())
    {
    
    
        auto t = q.front();
        q.pop();

        if (t == end) return d[t];

        int distance = d[t];
        int k = t.find('x');
        int x = k / 3, y = k % 3;
        for (int i = 0; i < 4; i ++ )
        {
    
    
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < 3 && b >= 0 && b < 3)
            {
    
    
                swap(t[a * 3 + b], t[k]);
                if (!d.count(t))
                {
    
    
                    d[t] = distance + 1;
                    q.push(t);
                }
                swap(t[a * 3 + b], t[k]);
            }
        }
    }

    return -1;
}

int main()
{
    
    
    char s[2];

    string state;
    for (int i = 0; i < 9; i ++ )
    {
    
    
        cin >> s;
        state += *s;
    }

    cout << bfs(state) << endl;

    return 0;
}

Esta pregunta requiere comprimir el estado actual para facilitar el juicio sobre si se logró el objetivo. Se utiliza una tabla hash de cadenas para determinar el peso, y las otras ideas son las mismas que caminar por un laberinto.

Aquí hay otros amigos relacionados con imágenes.

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环。

所有边的长度都是 1,点的编号为 1∼n。

请你求出 1 号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1。

输入格式
第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 a 和 b,表示存在一条从 a 走到 b 的长度为 1 的边。

输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。

数据范围
1≤n,m≤105
输入样例:
4 5
1 2
2 3
3 4
1 3
1 4
输出样例:
1

Código:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e5+10;
int h[N],e[N],ne[N];
int n,m,idx;
int d[N];
void add(int a,int b)
{
    
    
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int bfs()
{
    
    
    queue<int> q;
    memset(d, -1, sizeof d);
    d[1]=0;
    q.push(1);
    while(q.size())
    {
    
    
        auto t=q.front();
        q.pop();
        for(int i=h[t];i;i=ne[i])
        {
    
    
            int j=e[i];
            if(d[j]==-1)
            {
    
    
                d[j]=d[t]+1;
                q.push(j);
            }
        }
    }
    return d[n];
    
}
int main()
{
    
    
    cin>>n>>m;
    memset(h, -1, sizeof h);
    for(int i=0;i<m;i++)
    {
    
    
        int a,b;
        cin>>a>>b;
        add(a, b);
    }
    cout<<bfs()<<endl;
}

La diferencia entre este problema y el camino más corto a través del laberinto es que requiere el uso de listas de adyacencia. Todo lo demás es una plantilla.

Supongo que te gusta

Origin blog.csdn.net/qq_57109165/article/details/120748696
Recomendado
Clasificación