Dijkstra on a 2D Plane (Rust)
TL;DR
For maze-solving problems where you need to count the number of obstacles or only count when performing special operations, Dijkstra's algorithm can apparently be used to solve them.
Approach
A priority queue (BinaryHeap) pops the maximum value first, so when we want to count certain operations, we push negative values into the priority queue. This way, entries with larger counts are popped later. Just like in BFS, we prepare a dist array, and when we first visit (x, y), we negate the popped value and store it in dist. This makes dist[y][x] the minimum value at that point. Thus, we can keep track of the count of special operations performed. It's something like 0-1 BFS (though I don't fully understand 0-1 BFS).
On a separate note, I learned for the first time from the docs that Rust's tuple Ord evaluates elements sequentially from the front.
The sequential nature of the tuple applies to its implementations of various traits. For example, in PartialOrd and Ord, the elements are compared sequentially until the first non-equal set is found.
Prerequisites
Example 1: ARC005 C - Property Destruction! Takahashi
Count the number of times we hit "#" from start to goal. If the count is 2 or less at the goal, output YES; otherwise, NO.
Example 2: A - Range Flip Find Route
DP is apparently easier for this one. During the search, we want to count the number of transitions from white to black, or black to white. In other words, we want to find the minimum number of times the value changes from the previous one.
Example 3: D - Wizard in Maze
Count the number of warps. Warps cost -1. The intended solution using 0-1 BFS, or only warping when normal movement fails, would likely be faster. This one is a bit special: to prevent warp values from contaminating the results (since a cell might be reachable via normal movement even if we haven't visited it yet), we need to verify at the beginning of the while loop that the cell hasn't been visited.
Example 4: J - Land Leveling
We want to find the minimum cost of traveling from the bottom-left to the bottom-right, and then from the bottom-right to the top-right. However, since a path that has already been traversed can be used at zero cost, simply running Dijkstra twice won't work. Instead, we need to fix an intermediate point and find the minimum total cost from all three points (bottom-left, bottom-right, top-right) to that point.
After running Dijkstra three times, we compute the cost at every point and find the minimum. However, since the intermediate point is counted three times during the search, we need to reduce its cost to a single occurrence by subtracting the point's cost twice.
Addendum
I'll add solutions as I find them.