C - Knight Fork Editorial by Nyaan
問題文をナイーブな全探索で実装する、すなわち \((x, y)\) を広い範囲から列挙して \((x_1, y_1)\) からの距離も \((x_2, y_2)\) からの距離も \(\sqrt{5}\) になる点があるか調べると次のようなコードになると思います。
# 距離の 2 乗を計算する関数
def dist_sq(a, b, c, d):
return (a - c) ** 2 + (b - d) ** 2
# 答えを求める関数
def solve(x1, y1, x2, y2):
for x in range(-2 * 10 ** 9, 2 * 10 ** 9 + 1):
for y in range(-2 * 10 ** 9, 2 * 10 ** 9 + 1):
if dist_sq(x, y, x1, y1) == dist_sq(x, y, x2, y2) == 5:
return "Yes"
return "No"
しかしこれは計算量が (\(x\) の範囲) \(\times\) (\(y\) の範囲) となってしまうため TLE してしまいます。
これはこの問題に限らず重要な話ですが、困った時はサンプルを図に書いて考察する のが問題を解く上で大事です。さっそく図を書いてみましょう。
サンプル \(1\) において、\((x_1, y_1)\) および \((x_1, y_1)\) から距離 \(\sqrt{5}\) の格子点を丸、\((x_2, y_2)\) および \((x_2,y_2)\) から距離 \(\sqrt{5}\) の格子点を三角で示したのが以下の図になります。
図を描いて考えると、どうやら調べる必要があるのは 「\((x_1, y_1)\) を中心とした \(4 \times 4\) 四方に含まれる点」だけでよいことが分かると思います。なぜならば、その範囲の外の点は距離が \(3\) 以上になり、\(\sqrt{5}\) を超えてしまうからです。
探索範囲を改善したプログラムは以下の通りです。このプログラムは十分高速に動作するのでこれで AC することができます。
# 距離の 2 乗を計算する関数
def dist_sq(a, b, c, d):
return (a - c) ** 2 + (b - d) ** 2
# 答えを求める関数
def solve(x1, y1, x2, y2):
for x in range(x1 - 2, x1 + 3):
for y in range(y1 - 2, y1 + 3):
if dist_sq(x, y, x1, y1) == dist_sq(x, y, x2, y2) == 5:
return "Yes"
return "No"
x1, y1, x2, y2 = map(int, input().split())
print(solve(x1, y1, x2, y2))
posted:
last update: