Aula 03 - Busca em Largura
Agora que já implementamos por completo a busca em profundidade (DFS) podemos dar um novo passo na resolução do labirinto: encontrar a saída mais próxima.
O algoritmo básico da DFS não se preocupa com o tamanho dos caminhos, apenas com existir um caminho. Ou seja, ele é muito útil quando queremos
- encontrar todas as casas acessíveis a partir de um certo lugar
- detectar ciclos: maneiras de sair de uma casa e voltar para ela
Isso vem da própria definição que usamos para criar nosso algoritmo recursivo, que não tinha nada sobre o comprimento de um caminho, apenas sobre a existência de um caminho.
Por isso a busca em largura vai colocar a distância como parte principal de seu funcionamento. Iremos explorar os caminhos em "ondas":
- primeiro encontraremos todas casas acessíveis usando caminhos de tamanho máximo 1
- em seguida, encontraremos todas as casas acessíveis usando caminhos de tamanho máximo 2
- repetimos essa ideia, encontrando as casas acessíveis usando caminhos cada vez maiores.
Um ponto importante aparece aqui: saber as casas acessíveis usando caminhos de tamanho no máximo $n$ nos ajuda a encontrar todas as casas acessíveis usando caminhos de tamanho no máximo $n+1$! Fazemos isso colocando as casas a serem visitadas em uma Fila.
A fila
Usaremos uma ADT para fila com as seguintes opções:
NOVA_FILA()
REMOVE_PRIMEIRO(F)
- devolve o primeiro elemento da fila e o removeADICIONA_NO_FIM(F, EL)
- adiciona um elemento no fim da filaVAZIA(F)
- retornaVERDADEIRO
seF
estiver vazia
Busca em Largura - alto nível
Na última aula fizemos simulações do funcionamento da busca em largura e criamos um pseudo código em alto nível na lousa. Vejamos as variáveis necessárias para seu funcionamento
LABIRINTO L
FILA F
- guarda a ordem em que visitaremos as casasDIST
- matriz que guarda a distância até a fonte. Tem valor -1 para casas não visitadasfI, fJ
- posição da fontedI, dJ
- posição do destino
O algoritmo era parecido com o seguinte:
BFS(L, fI, fJ, dI, dJ, DIST, F)
ADICIONA_NO_FIM(F, (fI, fJ))
DIST[fI][fJ] = 0
ENQUANTO NÃO VAZIA(F) FAÇA
cI, cJ <- REMOVE_PRIMEIRO(F)
SE CHEGOU NO DESTINO ENTÃO
PARE O LOOP
FIM
PARA CADA VIZINHO vI, vJ NÃO VISITADO FAÇA
DIST[vI][vJ] = DIST[cI][cJ] + 1 # VISITOU
ADICIONA_NO_FIM(F, (vI, vJ))
FIM
FIM
SE CHEGOU NO DESTINO ENTÃO
USE A MATRIZ DIST PARA ENCONTRAR O TAMANHO DO CAMINHO
RECRIE O CAMINHO "ANDANDO PARA TRÁS" NAS DISTÂNCIAS
FIM
Seu desafio será transformar esse pseudo código alto nível em uma implementação completa da busca em largura. Volte para o PrairieLearn e use os testes para verificar sua implementação.