O cavalo quer o menor caminho.
Cada casa do tabuleiro vira um vértice. Cada movimento possível do cavalo vira uma aresta. A BFS explora o tabuleiro por distâncias crescentes até encontrar o destino.
Contexto do problema
Dados dois quadrados do tabuleiro, precisamos descobrir o menor número de movimentos do cavalo necessário para sair da origem e alcançar o destino.
Dois quadrados
Exemplo: e2 e4. O primeiro é a origem e o segundo é o destino.
Menor quantidade
Não basta encontrar um caminho. Precisamos garantir que seja o caminho com menos movimentos.
Número de movimentos
Imprimimos a frase pedida pelo problema com a distância encontrada.
f6 f6.
O tabuleiro é um grafo
Para resolver com grafos, basta reinterpretar o tabuleiro.
64 casas
Cada quadrado do tabuleiro representa um vértice.
a1, a2, ..., h8
Movimentos válidos
Existe uma aresta entre duas casas quando o cavalo pode ir de uma para a outra em um único movimento.
Os 8 movimentos possíveis do cavalo
O cavalo sempre faz um deslocamento em “L”: duas casas em um eixo e uma no outro.
#include <array>
#include <utility>
const std::array<std::pair<int, int>, 8> movimentos{{
{ 2, 1}, { 2, -1},
{-2, 1}, {-2, -1},
{ 1, 2}, { 1, -2},
{-1, 2}, {-1, -2}
}};
0 <= nx < 8 e 0 <= ny < 8.
Por que BFS?
A BFS percorre o grafo por camadas de distância.
Começa na origem
Origem entra na fila com distância 0.
Explora vizinhos
Todos os movimentos possíveis recebem distância +1.
Primeiro encontro
Quando o destino é retirado da fila, aquela distância é mínima.
BFS animada — e2 até e4
Este exemplo precisa de 2 movimentos. A animação mostra a expansão por camadas.
O mesmo exemplo como grafo
Cada bolinha é uma casa do tabuleiro. Cada linha é um movimento válido do cavalo que a BFS está considerando neste trecho.
Algoritmo em C++17
#include <array>
#include <queue>
#include <string>
#include <tuple>
#include <utility>
int bfs(const std::string& origem, const std::string& destino) {
int x = origem[1] - '1';
int y = origem[0] - 'a';
int alvo_x = destino[1] - '1';
int alvo_y = destino[0] - 'a';
std::array<std::array<bool, 8>, 8> visitado{};
std::queue<std::tuple<int, int, int>> fila;
visitado[x][y] = true;
fila.push({x, y, 0});
const std::array<std::pair<int, int>, 8> movimentos{{
{2,1}, {2,-1}, {-2,1}, {-2,-1},
{1,2}, {1,-2}, {-1,2}, {-1,-2}
}};
while (!fila.empty()) {
auto [atual_x, atual_y, distancia] = fila.front();
fila.pop();
if (atual_x == alvo_x && atual_y == alvo_y)
return distancia;
for (auto [dx, dy] : movimentos) {
int nx = atual_x + dx;
int ny = atual_y + dy;
if (nx >= 0 && nx < 8 &&
ny >= 0 && ny < 8 &&
!visitado[nx][ny]) {
visitado[nx][ny] = true;
fila.push({nx, ny, distancia + 1});
}
}
}
return -1;
}
Entrada e saída do exemplo
Exemplo de entrada
Exemplo de saída
1 movimento
c3 é diretamente alcançável pelo cavalo a partir de b1.
6 movimentos
A BFS expande várias camadas até alcançar o destino.
0 movimentos
A origem já é o destino; a primeira posição retirada da fila resolve o caso.
O que o aluno precisa guardar
Modelagem
Casa = vértice. Movimento válido = aresta.
BFS
Explora por níveis usando uma fila.
Menor caminho
Em grafo não ponderado, a primeira distância encontrada pela BFS é mínima.
| Elemento do problema | Interpretação em grafos |
|---|---|
| Casa do tabuleiro | Vértice |
| Movimento do cavalo | Aresta |
| Quantidade de movimentos | Distância |
| Estrutura auxiliar | Fila |
| Algoritmo | BFS |