競技プログラミング

ABC389のD問 “Squares in Circle” 図解説【Python】【AtCoder】


考え方

まず入力例1のケースを図解します。

円の半径が2(R=2)の時、その中に書ける正方形は5つです。

計算を簡単にするために、円の4分の1だけを考えます。(最終的に4倍します)

4分の1にしました。半径はRcmで、円の中心から次の正方形までの距離は0.5cmになります。

ここから、半径に対して垂直な区分線(オレンジ色の部分)を調べます。

正方形の高さは必ず1cmですので、高さがわかれば正方形がいくつ入るかがわかります。

高さは三平方の定理から求めることができます。

R2=height2+0.52R^2 = height^2 + 0.5^2

ここでポイントがあります。

4分の1を計算するときに、下図の黄色と緑色にかかる正方形は含めないよう注意します。

まず円の中心にかかっている正方形(黄色)は、1つしかなく、これを含めて数えるとのちに4倍してしまうので数えません。(4倍した後に+1をします)

また、円に含まれる正方形が風車のような形をしている点も考慮します、緑色部分の正方形は左上の扇形にもかかっているので、4分の1の計算をする際にここを数えないようにします。

ですので、実際に数え上げるときは下図のオレンジ色の高さからスタートして数えます。

では、実装しましょう!

コード全文

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import math
r = int(input())
cnt = 0

for i in range(1, r):
    height = math.sqrt( r**2 - (i+0.5)**2)
    height += 0.5

    cnt += int(height)

cnt = cnt*4 + 1

print(cnt)

コード解説

まずは必要なモジュールと入力を書きます。

cnt変数で正方形の数を数え上げていき、最後にcnt変数をprintします。

1
2
3
import math
r = int(input())
cnt = 0

4分の1中の正方形の数を数える

先ほど説明したように、中心から底辺が1.5cmのオレンジ色部分の高さから数えていきます。

rangeを1始まりにし、heightの計算でiに0.5を足すことで、底辺1.5cmになっています。

1
2
3
4
5
for i in range(1, r):
    height = math.sqrt( r**2 - (i+0.5)**2)
    height += 0.5

    cnt += int(height)

3行目でheight += 0.5をしていますがこれも重要なポイントです。

円のx軸にかかっている正方形は高さが0.5cmでぶった斬れていますので、0.5cm足して底下げをしています。要は図のピンクの四角形をきちんと数えるためです。

最終的にこのオレンジの線が何センチかで、正方形が何個存在するかわかります。

それがcnt += int(height) になります。

円全体の数に直す

1
cnt = cnt*4 + 1

4倍し、中心の1個を足して終了です。