Este é um exemplo do que eu quero fazer via código. Eu sei que você pode usar a pesquisa de pontos de salto para passar facilmente do nó verde para o nó vermelho sem problemas ou mesmo A *. Mas como você calcula isso com deformações.
Na imagem, você pode ver que são necessários apenas oito movimentos para ir do nó verde para o nó vermelho ao seguir o caminho azul. O caminho azul move instantaneamente sua posição de um nó roxo para o próximo. O espaço no meio que custa 2 movimentos é um ponto entre duas zonas de distorção que você deve mover para chegar.
É claramente mais rápido seguir o caminho azul, já que você só precisa mover metade (aproximadamente) até o caminho amarelo, mas como faço isso programaticamente?
Com o objetivo de resolver esse problema, vamos supor que haja vários "warps" roxos ao redor do gráfico que você possa usar, E sabemos exatamente para onde cada ponto roxo se distorcerá e onde estão no gráfico.
Algumas urdiduras roxas são bidirecionais e outras não, o que significa que, às vezes, você só pode inserir uma urdidura de um lado, mas não voltar após a deformação.
Pensei na solução e só concluí que seria capaz de calcular o problema verificando a distância de cada ponto de distorção (menos os pontos unidirecionais) e a diferença entre esses pontos e os pontos próximos a eles. .
O programa teria que descobrir de alguma forma que é mais benéfico realizar o segundo warp, em vez de caminhar desde o primeiro salto. Então, em vez de mover 6 pontos, entortar e depois mover os 8 passos restantes a pé (o que também é mais rápido do que não usar deformações), seriam necessários os 6 movimentos, depois os dois movimentos para o segundo warp.
Edição: Eu percebi que o caminho azul vai realmente levar 12 movimentos, em vez de 8, mas a questão permanece a mesma.
fonte
Respostas:
A maioria dos algoritmos de localização de caminhos é definida em termos de gráficos, não em termos de grades. Em um gráfico, uma conexão entre dois nós distantes não é realmente um problema.
No entanto, você deve tomar cuidado com suas heurísticas. Nos buracos de minhoca, a distância mínima entre dois nós não é mais a distância euclidiana e a distância não satisfaz a desigualdade do triângulo. Tais heurísticas são inadmissíveis para A *. Portanto, você não pode usar A * facilmente.
Obviamente, algoritmos de localização de caminhos como o Dijkstra que não usam uma heurística ainda funcionarão. É mais como uma pesquisa abrangente e selecionará seus buracos de minhoca sem esforço extra. No entanto, Dijkstra visitará mais nós que A * com uma boa heurística. (Dijkstra é equivalente a A * com
heuristic(x) = 0
.)Acho que A * funcionará se você usar uma heurística que trate todos os buracos de minhoca de saída como um buraco de minhoca diretamente para o alvo: a heurística pode subestimar a distância, mas nunca deve superestimá-la. Ou seja, a heurística seria:
Para uma heurística muito precisa, você pode (recursivamente) adicionar a distância do ponto final do buraco de minhoca até a meta ou o próximo buraco de minhoca. Ou seja, como pré-cálculo, você poderia realizar a localização de um caminho no subgrafo (totalmente conectado) contendo todos os buracos de minhoca e a meta, em que a distância entre dois nós é a distância euclidiana. Isso pode ser benéfico se o número de buracos de minhoca for muito menor que o número de células alcançáveis em sua grade. A nova heurística seria:
Como o @Caleth aponta nos comentários, tudo é muito sintonizável e podemos melhorar a primeira heurística do buraco de minhoca sem fazer um caminho completo pela rede do buraco de minhoca, adicionando a distância entre a última saída do buraco de minhoca e a meta. Como não sabemos qual saída de buraco de minhoca será usada por último e não devemos superestimar, temos que assumir a saída mais próxima da meta:
fonte
dijkstra_heuristic(x) = 0
wormhole_path_distance
que a pesquisa por subgráficos e menos subestimada do que a "todas as saídas estão na meta".Você tem um gráfico com 6 vértices em uma grade com coordenadas:
Você pode gerar um gráfico completo nesses vértices e atribuir um custo a cada aresta, onde o custo é
MAX( ABS( x1 - x2 ), ABS( y1 - y2 ) )
para arestas padrão e um custo de 0 para buracos de minhoca.Isso fornecerá os custos (como uma matriz de adjacência):
Se houver distorções unidirecionais, crie apenas arestas no gráfico (ou matriz de adjacência) que vão nessa direção, mas não no oposto.
Você pode usar o algoritmo de Dijkstra com uma fila de prioridade .
Comece
A
e empurre cada extremidade adjacente para a fila de prioridade:Formato: (caminho: custo)
À medida que os itens são empurrados para a fila - acompanhe o custo mínimo de cada vértice e só empurre caminhos para a fila se for um custo menor que o custo mínimo existente.
Remova o primeiro item da fila e, se o custo ainda corresponder ao custo mínimo, empurre de volta todos os caminhos compostos formados por esse caminho e suas bordas adjacentes para a fila de prioridade (se os caminhos compostos tiverem um custo menor que o mínimo existente):
Remover:
(A-B : 7)
(A-B-A : 14)
- rejeite como custo mais alto(A-B-C : 7)
- rejeite como o mesmo custo(A-B-D : 13)
- rejeite como custo mais alto(A-B-E : 19)
- rejeite como custo mais alto(A-B-F : 19)
- rejeite como custo mais altoRemover
(A-C : 7)
(A-C-A : 14)
- rejeite como custo mais alto(A-C-B : 7)
- rejeite como o mesmo custo(A-C-D : 10)
- rejeite como o mesmo custo(A-C-E : 16)
- rejeite como o mesmo custo(A-C-F : 16)
- rejeite como o mesmo custoRemover
(A-D : 10)
(A-D-A : 20)
- rejeite como custo mais alto(A-D-B : 16)
- rejeite como custo mais alto(A-D-C : 13)
- rejeite como custo mais alto(A-D-E : 10)
- inserir na fila(A-D-F : 16)
- rejeite como o mesmo custoAgora a fila terá a seguinte aparência:
Remover
(A-D-E : 10)
(A-D-E-A : 26)
- rejeite como custo mais alto(A-D-E-B : 22)
- rejeite como custo mais alto(A-D-E-C : 19)
- rejeite como custo mais alto(A-D-E-D : 10)
- rejeite como o mesmo custo(A-D-E-F : 12)
- inserir na filaEntão a fila é:
Remova
(A-D-E-F : 12)
, verifique se você chegou ao nó de destino com um custo de 12.Nota: os caminhos
(A-B-C-D-E-F)
,(A-C-D-E-F)
e(A-D-E-F)
todos têm o mesmo custo mínimo de 12.fonte
Configure uma matriz contendo todos os vértices e use o algoritmo de Floyd-Wallenstein ou o algoritmo de Bellman-Ford. Ambos resultarão em uma matriz com os caminhos mais curtos possíveis entre todos os pontos. Você pode percorrer a matriz para encontrar o caminho mais curto que conecta dois pontos. (seu problema é o mesmo que um TSP assimétrico).
fonte