平面上でのダイクトストラ (rust)
TL;DR
迷路を解くような問題で、障害物の数だったり、なんか特殊な処理するときだけ数える、みたいなやつはダイクトストラを使えば解けるらしい。
考え方
プライオリティキュー(BinaryHeap)は、最大値のものから取り出されていくので、数えたい処理のときはマイナスの値にしてプライオリティキューに入れていけば、値が大きいものほど取り出されなくなる。BFSのときと同じようにdistを作っておいて、最初にdistの(x, y)に訪れたときに取り出されたものにマイナスをかけてdistに格納しておけば、distの(x, y)はその時点での最小値になる。なので、何らかの特殊な処理をした値の数を保存することができる。0-1BFSのようなものっぽい(0-1BFSがわかってない)。
それはそうとdocsを読んで初めて知ったんですがrustのtupleのOrdは前から順番に大きさを評価していくんですね。
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.
前提
例1 ARC005 C - 器物損壊!高橋君
スタートからゴールまでに"#"にあたる回数を数えて、ゴール時点で回数が2以下ならYES、そうじゃなければNO。
例2 A - Range Flip Find Route
DPのほうが楽らしい。探索するときに、白から黒、もしくは黒から白に切り替わる数を数えたい。つまり、前回の値と違う数になる場合の数の最小値を求めたい。
例3 D - Wizard in Maze
ワープ回数を数える。ワープのときにコスト-1で計算。想定解の0-1BFSとか、通常の移動ができなかったときだけワープさせるとかしたら早くなりそう。ちょっと特殊でワープしたときの値が混入することを防ぐために(その時点では行ってなくても通常の移動で行ける可能性があるので)、whileループのはじめで訪れてないことを確かめておく必要がある。
例4 J - 地ならし
左下から右下、右下から右上にいくときの最小コストを求めたい。ただし、一回通った道はコスト0で通ることができるので、単純に2回ダイクトストラするだけではだめ。なので、経由点を1点定めて、そこまでの3点(左下、右下、右上)からのコストの合計値が一番小さいものを求める必要がある。
3回ダイクトストラをしたあと、すべての点のコストを求めて、その最小値を求める。ただし、探索する際にその点は3回繰り返されるので、そのコストを1回分にする必要があり、2回分その点のコストを引いている。
追記欄
見つけたら解答を書いていく。