ひとまず一次元の問題として考える。つまり、数直線上のある地点tに降り立って、各点x1,x2,...,xnに行って帰る問題である。さらにx1≤x2≤...≤xnと仮定する。最後に訪れる点をxkとする時、総距離は
2∣t−x1∣+....+2∣t−xk−1∣+∣t−xk∣+2∣t−xk+1∣+...+2∣t−xn∣
となる。絶対値関数の和は下に凸になり、区分する点の中央値で最小値を取ることを使えそうな気がする。しかし、係数が邪魔なので開いて並べる:
∣t−x1∣,∣t−x1∣,...,∣t−xk−1∣,∣t−xk∣,∣t−xk+1∣,...,∣t−xn∣,∣t−xn∣
これら2n−1個の点の真ん中にある点xlは(奇数個だから)一点に定まるので、上の式にt=xlを代入すると最小値が求まる。具体的には、右側にあるn−1個のxiを足して左側にあるn−1個のxiを引けばよい。最後に訪れる点をn通り試せば答えがわかる。二次元の場合もまったく同じで、x方向とy方向について独立に求めてから和を取ればよい。
実装について。いろいろやり方はありそうだけど、ソートされた列に順序を保って挿入・削除する操作があって、さらに区間の和が高速に求まれば直接的にシミュレーションできるのでそれがもっとも簡単に見える。平衡二分木ならどちらもO(logN)でできる。
けっきょく真ん中になりえる点は1個か2個しかないので、それを試すだけでよいらしい。途中で気づきたかった。