【AtCoder】パ研合宿2023 第1日「SpeedRun」D - Bishop

問題

解法

 (x, y) に操作を行うと  (x + K, y + K) または  (x + K, y - K) に移る。

つまり、 (x + y, x - y) に操作を行うと  (x + y + 2 K, x - y) または  (x + y, x - y - 2 K) に移る。

ここで  a = x + y, b = x - y という変数を導入すると

 (a, b) は操作後に  (a + 2 K, b) または  (a, b - 2K) に移るといえる。

これで  a b を独立に考えることができるようになったため、答えは  \left \lceil \frac{|a|}{2K} \right \rceil + \left \lceil \frac{|b|}{2K} \right \rceil になる。

#include "my_template.hpp"
using namespace std;

void solve() {
    I64(K, X1, Y1, X2, Y2);
    i64 x = abs(X1 - X2), y = abs(Y1 - Y2);
    i64 a = abs(x + y), b = abs(x - y);
    i64 ans = ceil(a, 2 * K) + ceil(b, 2 * K);
    print(ans);
    return;
}

int main() {
    solve();
    return 0;
}

感想

無限人通していてかなり厳しい気持ちになった。

45度回転をマンハッタン距離の最大化の文脈でしか使えていないということが判明。 もうちょっと一般化して、 x+y, x-y という変数を導入することで式変形ができるようになる手法、くらいに思っておくと良さそう。

マンハッタン距離の最大化

 (x_1, y_1), (x_2, y_2), ... , (x_n, y_n) が与えられる。 点  (x_q, y_q ) とのマンハッタン距離の最大値について

 (a_i, b_i) = (x_i + y_i, x_i - y_i) とおくと

 \max_{1 \leq i \leq n} ( |x_i - x_q| + |y_i - y_q| )

 = \max_{1 \leq i \leq n} ( \max(x_i - x_q, x_q - x_i ) + \max(y_i - y_q, y_q - y_i) )

 = \max_{1 \leq i \leq n} ( x_i - x_q + y_i - y_q, x_i - x_q + y_q - y_i, x_q - x_i + y_i - y_q, x_q - x_i + y_q - y_i)

 = \max_{1 \leq i \leq n} ( a_i - a_q, b_i - b_q, b_q - b_i, a_q - a_i)

 = \max_{1 \leq i \leq n} ( \max( |a_i - a_q|, |b_i - b_q |))

となり、 a, b それぞれで最大値を求めてから大きい方を選択すれば求められるというテクニックのこと。

またこの  \max( |a_i - a_q|, |b_i - b_q |)  (a_i, b_i)  (a_q, b_q) のチェビシェフ距離と言う。