JoeJ said:
Say you pick one random source vertex on the mesh, and 10 random target vertices. You start at the source, and keep Dijkstra running until all 10 targets have been found. No changes or extensions to the algorithm are needed, and all 10 paths will be the shortest possible as expected. I guess with A star this can't work, because the heuristic involves a target.
The heuristic can be anything that “optimistically estimates remaining path”. “Optimistically” here means less or equal to actual remaining path. Best performance is obtained when estimate is exactly the remaining distance. If the estimate is smaller, performance goes down but you keep getting optimal paths. Estimates higher than remaining costs are faster than best performance at the cost of NOT always getting the optimal path.
So you could pick the constant 0 as the estimate, and it will work (it is less then any remaining distance). The constant 1 as suggested by frob is the same idea, except that may lead to non-optimal paths if you have paths with lengths smaller than 1.
The effect of picking a fixed value like 0 is that A* loses all steering towards a destination, and will spread out in all directions just like Dijkstra does. As frob already said, Dijkstra and A* with estimate 0 are equivalent. As for the stop condition, as long as you don;t terminate the process, A* with estimate 0 will happily continue to expand the searched area until you've had enough or until it run s out of vertices.
JoeJ said:
For games this would be useful if you want to find the closest target out of many options. But if that's 4 nearby targets for example, and each can be found by a straight path, running A star 4 times is likely still faster.
Pretty much all A* code at the Internets assumes a single target that you want to reach so the extremely common estimate is distance to that target. The algorithm itself however doesn't demand that, any estimate equal or less than real remaining path-cost will do. So it's fine to write an estimator that computes remaining cost for all your 4 targets and then returns the smallest value. The disadvantage here is that the estimator gets more complicated and deciding you reached a target gets more complicated.
You can however avoid those disadvantages if you modify the problem a bit. Say the initial starting vertex is S, and your four target vertices are D1 to D4 (I use Dx as shorthand of “one of D1, D2, D3, or D4".). Add a new vertex T, and edges with cost 0 from D1..D4 to T. Next, swap direction of all edges but keep the costs as they were. Also swap target vertex with starting vertex. Thus the search starts at T and ends at S. This is a classic A* search. The first step in the path will move to one of the D1..D4 nodes and then it gives the shortest path to S. This is optimal, since the edge from T to any Dx vertex didn't cost anything.
Also, while you swapped direction of the edges, you kept original costs. Those costs are thus valid when you follow the same path from S to Dx in the unmodified graph.
A few practical notes: You don't need to literally swap the direction of the edges in the graph. If you have a way to find incoming edges at a vertex, you can simply follow incoming edges rather than outgoing edges in the implementation. Also, if you look closely at the first iteration of the A* algorithm, you'll find that it deletes the T node and adds all Dx nodes. You can instead write code that does exactly that, and then start the A* algorithm. The algorithm will be one iteration shorter and the initial node will be at one of the Dx vertices.