irisruneです。今週もコンテストは出ていませんでした、コンテスト開催日時に合わせて色々調整することも考えないといけませんね。
C問題よりも難しいと感じる人もいたそうです。確かに問題文だけ見るとC問題の方が単純そうには見えました(まだC問題は解いていませんが)。
import sys import numpy as np def main(): n = int(input()) balls = [[int(e) for e in input().split()] for _ in range(n)] if n == 1: print(n) sys.exit() diff = {} for i in range(n): for j in range(n): if i == j: continue if ((balls[i][0] - balls[j][0]), (balls[i][1] - balls[j][1])) in diff: diff[((balls[i][0] - balls[j][0]), (balls[i][1] - balls[j][1]))] += 1 else: diff[((balls[i][0] - balls[j][0]), (balls[i][1] - balls[j][1]))] = 1 print(n - max(diff.values())) main()
割と小難しそうな問題ですが、結論から言えばをすべての
の順列について計算し、最も出現回数の多いペアについてその回数を
から引いた数が答えになります。
このように解ける理由としては、問題の条件にある『または
』がポイントとなっています。
この条件により、番目のボールについて(
は互いに相異なる)、
となることはありません。よって
を適当に選んだとして、
番目のボールの次に
番目のどちらかのボールを選んだとき、両方のボールについて回収するためのコストが
になるということはありません(少なくとも片方のボールを回収するためにコスト
が必要)。
これにより、任意の座標の差のペアについて、その出現回数はそれぞれの値を
として置いたときにコスト
で回収できるボールの数となります。そのため、
座標の差のペアそれぞれについて出現回数の最大値を求めればよいということになります。
実装については辞書型を使えばそれほど難しくないはずです。辞書型の要素数の最大値を出す処理の計算量が分からないですがそれ以外の処理の計算量はになります。
雑記
- コーナーケースとして
の場合、当然ながら座標の差というものはないので(辞書型の)要素数の最大値を求めようとするとREになります。
と条件が非常に緩いので、他の解き方でもなんとかなりそうな気はしますがよい方法が思いつかないです。
- 当初はなんとなくワーシャルフロイド法を使うことなど考えていましたが、
を定めないとコストの合計が出せない上に、
と座標の取り得る値が非常に広いため、
を全通り試すことが不可能でした。
座標の差のペアとして出現する値に絞れば
くらいで解けるかもしれませんが、ペアの出現回数から直接答えを求める方法でよいという結論になってしまうので…
- 当初はなんとなくワーシャルフロイド法を使うことなど考えていましたが、