実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 828
問題概要
座標平面上に の大きさのタイルが下図のように敷き詰められている。高橋君は、始め点
にいて、「上下左右の方向と正の整数
を選ぶ。その方向に
だけ進む」という移動を好きなだけ繰り返す。高橋君が異なるタイルを通るたび、高橋君は通行料を
支払う。高橋君が点
にたどり着くために支払わなければならない通行料の最小値を求めよ。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/Y/Yuulis/20240623/20240623140222.png)
制約
- 入力はすべて整数。
考察
まず、簡単のためスタートとゴールはタイルの左側の正方形にあるとして考えよう。仮に右側にあったとしても、同じタイルの移動ならば通行料はかからないので問題ない。具体的には、以下の処理を行う。
ならば、
を 1 減らす。
についても同様。
この処理をした後、 とおく。以降は、第1象限の左下から右上への移動を考える。それ以外の移動については、各移動の符号を逆にすればよい。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/Y/Yuulis/20240623/20240623164129.png)
上図において、 から
と
への移動をそれぞれ考える。このとき、
である。
まず、 について。図のように、上移動を繰り返しながら、タイルの左側の正方形に来たとき、現在の
座標が
より小さいならば右移動を行う (図ではルートが重ならないように最後の方で右移動を行っているが、スタート直後から行って良い) 。こうすることで、
軸方向の移動のコストはかからなくなり、通行料としては
のみを払えばよいことになる。
一方、 については、先ほどと逆に、右移動を繰り返しながら、タイルの左側の正方形に来たとき、現在の
座標が
より小さいならば上移動を行う。 このときは、
軸方向の移動のコストが
となり、
と愚直に移動するよりも 1 少なく済む。
まとめると、求める通行料の最小値 は、
で計算できる。
コード
#include <bits/stdc++.h> using namespace std; using ll = long long; // ======================================== // int main() { ll S_x, S_y, T_x, T_y; cin >> S_x >> S_y >> T_x >> T_y; S_x -= (S_y + S_x) % 2; T_x -= (T_y + T_x) % 2; ll dx = abs(T_x - S_x); ll dy = abs(T_y - S_y); cout << dy + max(0LL, dx - dy) / 2 << endl; }
実装時間: 45分