公開日 :
更新日 :

マンハッタン距離とチェビシェフ距離

マンハッタン距離チェビシェフ距離
式\(| \Delta x | + | \Delta y |\)\(\rm{max}| \Delta x |, | \Delta y |\)
動き方上下左右に1歩(基盤の目の道)斜めも1歩(将棋の王将)
距離 \(r\) 以内の形ひし形軸に並行な正方形
軸ごとに分けやすいもの総和(和は分けられる)最大値・範囲判定(\(\rm{max}\) は分けられる)
マンハッタン (r=2)     チェビシェフ (r=2)
    . . * . .            * * * * *
    . * * * .            * * * * *
    * * * * *            * * * * *
    . * * * .            * * * * *
    . . * . .            * * * * *

将棋の王将が \((0,0)\) から \((5,2)\) へ移動する手数は、斜め \(2\) 回 \(+\) 横 \(3\) 回 \(= \rm{max}(5,2)\)。

マンハッタン距離とチェビシェフ距離の変換

\(45^{\circ}\) 回転 \((u = x + y, v = x \ – \ y)\) で、マンハッタン距離とチェビシェフ距離は入れ替わる。
「和」と「\(\rm{max}\)」を行き来できるので、求めたいものに合う形に直すと軸ごとに分けて解ける。

変換公式

\(u = x + y, v = x \ – \ y\) と置く。

元の距離回転後
マンハッタン \(| \Delta x | + | \Delta y |\)\(\rm{max}| \Delta u |, | \Delta v |\)(チェビシェフ)
チェビシェフ \(\rm{max}| \Delta x |, | \Delta y |\)\((| \Delta u | + | \Delta v |) / 2\) (マンハッタンの半分)

ひし形を \(45^{\circ}\) 回すと正方形になる、という関係。

証明(\(a = \Delta x, b = \Delta y\))

マンハッタン → チェビシェフ : 絶対値は「符号を選んで大きいほう」なので \(|a| + |b| = \rm{max}(a + b, a \ – \ b, -a + b, -a \ – \ b) = \rm{max}(|a + b|, |a \ – \ b|) = \rm{max}(| \Delta u |, | \Delta v |)\)

チェビシェフ → マンハッタン : \(|a + b| + |a \ – \ b|\) は、同符号なら \((|a| + |b|) + |a| \ – \ |b|\)、異符号でも同様で、どちらも \(2 \cdot \rm{max} (|a|, |b|)\) よって \(\rm{max} (|\Delta x|, |\Delta y|) = (|\Delta u| + |\Delta v|) / 2\)

どちらに直すか

求めたいものと同じ形の距離に直すと、軸ごとに分けられる。

求めたいもの直す先分けられる理由
距離の最大値\(\rm{max}\) の形(チェビシェフ)\(\rm{max}\) と \(\rm{max}\) は順番を入れ替えられる
距離の総和和の形(マンハッタン)和と和は順番を入れ替えられる
距離 \(r\) 以内の点\(\rm{max}\) の形(正方形)軸に平行な正方形 → \(2\) 次元累積和などが使える
  • マンハッタンの最大値 → \(u, v\) に直して(最大 − 最小)の大きいほう。
  • チェビシェフの総和 → \(u, v\) に直して \(u\) の \(1\) 次元距離和 + \(v\) の \(1\) 次元距離和を \(2\) で割る。
  • マンハッタンの総和 → 回転不要。そのまま \(x, y\) に分ける。
  • チェビシェフの最大値 → 回転不要。そのまま \(\rm{max}(x\) の範囲\(, y\) の範囲\()\)

実装パターン

1.マンハッタン距離の最大値

ll umax = LLONG_MIN;
ll umin = LLONG_MAX;
ll vmax = LLONG_MIN;
ll vmin = LLONG_MAX;

rep(i, N) {
  ll u = x[i] + y[i];
  ll v = x[i] - y[i];
  umax = max(umax, u);
  umin = min(umin, u);
  vmax = max(vmax, v);
  vmin = min(vmin, v);
}

ll ans = max(umax - umin, vmax - vmin);

2.1次元の距離の総和(全ペア)

総和系の部品。
ソートして、各点について「自分より左の点との距離の和」を足す。

// Σ_{i<j} |a_i - a_j|
ll sum_abs_pairs(vector<ll> a) {
  sort(a.begin(), a.ned());
  ll res = 0;
  ll pre = 0;
  rep(i, (int) a.size()) {
    res += a[i] * i - pre;
    pre += a[i];
  }
  return res; 
}
  • マンハッタン距離の総和 = sum_abs_pairs(x) + sum_abs_pairs(y)
  • チェビシェフ距離の総和 = (sum_abs_pairs(u) + sum_abs_pairs(v)) / 2

3.1点からの重み付き距離和を全位置について

位置 \(k\) に重み \(\rm{W}[k]\) があるとき、各 \(x\) について \(\sum \rm{W}[k] \cdot | x \ – \ k| \) を \(\rm{O}(k)\) で。

vector<ll> dist_sum(const vector<ll>& W) {
  int K = W.size();
  vector<ll> res(K);

  ll cntL = 0;
  ll sumL = 0;
  ll cntR = 0;
  ll sumR = 0;

  rep(k, K) {
    cntR += W[k];
    sumR += W[k] * k;
  }

  rep(x, K) {
    res[x] = (x * cntL - sumL) + (sumR - x * cntR);
    cntL += W[x];
    sumL += W[x] * x;
    cntR -= W[x];
    sumR -= W[x] * x;
  }

  return res;
}

グリッド上のチェビシェフ距離の和に使うときは、人数を斜めのラインごとにまとめる。

int K = 2 * N - 1;
vector<ll> WU(K);
vector<ll> WV(K);
rep(i, N) {
  rep(j, N) {
    WU[i + j] += w[i][j];
    WV[i - j + N - 1] += w[i][j];
  }
}
auto GU = dist_sum(WU);
auto GV = dist_sum(WV);

4.斜め移動だけの距離

\(\pm 1, \pm 1\) にしか動けないとき:

  • \(x + y\) の偶奇は変わらない → 偶奇が違う \(2\) 点は到達不可能。
  • 偶奇が同じなら、必要な回数は \(\rm{max}(| \Delta x | , | \Delta y |) = (| \Delta u | + | \Delta v |) / 2\)。

偶奇でグループを分けてから、各グループでパターン2を使う。

練習問題