좌표평면상 어느 한 점에서 일정한거리 r만큼 떨어진 점들의 집합은? 원이죠. 반지름이 r인 원입니다.
입력받은 두개의 좌표를 중심으로하는 각 반지름 r1,r2인 두 원의 교점의 갯수를 구하는문제로 볼수있습니다. 대놓고 수학문제네요.
어렵지않은 문제지만 그림을 그려봤으니 시각자료로 써보겠읍니다(나름 신경써서 그렸습니다..)
각 두점에서 만나는, 접하는 (한점에서 만나는), 만나지않는 케이스입니다. 여기서 누락된 케이스는 두 원이 일치할때, 즉 중심과 반지름이 같을때 무한대의 교점을갖는 케이스입니다.
내/외 관점으로보면, 두점 사이 거리가 큰원의 반지름보다 클때 두 원은 서로의 외부에있습니다. 외부에 있다는 말의 의미는 작은원의 중심이 큰원 외부에 있다는겁니다. 이때는 두점사이 거리와 반지름합의 대소비교로 교점갯수를 구할수있습니다. 외부에있을땐 두점사이 거리가 반지름합보다 크다면 두 원은 만나지않습니다. 교점이 0이겠죠.
두점사이거리가 반지름합과 같다면 두원은 외접하고, 반지름합이 크다면 두점에서 만납니다.
내부 케이스는 또 다릅니다. 두점 사이거리보다 큰원의 반지름이 클때 작은원의 중심은 큰원 내부안에 있는 이른바 '내부 케이스'인데요. 이때는 교점을 메기는 기준이 좀 달라집니다. 이땐 두점 사이거리와 작은원 반지름의 합을 큰원 반지름과 대소비교하여 교점갯수를 세주면 됩니다.
이렇게 주저리 주저리설명한 내용을 최대한 간결하게 코드로 나타내봅시다. 이 문제는 if조건을 간결하게 쓰는게 중요할것같네요
T=int(input())
for _ in range(T):
x1,y1,r1,x2,y2,r2=map(int,input().split())
d=((x1-x2)**2+(y1-y2)**2)**(1/2)
sum_r=r1+r2
max_r=max(r1,r2)
min_r=min(r1,r2)
if d>max_r:
if d>sum_r:
cnt=0
elif d==sum_r:
cnt=1
else:
cnt=2
elif d<max_r:
if d==0:
if r1==r2:
cnt=-1
else:
cnt=0
elif d+min_r<max_r:
cnt=0
elif d+min_r==max_r:
cnt=1
elif d+min_r>max_r:
cnt=2
else:
cnt=2
print(cnt)
흠,, 이렇게도 답이 나오긴하는데요 쓸데없이 너무길죠?
관점을 바꿔봅시다. 내/외 관점이 아니라 어떨때 교점이(출력값이) -1,0,1,2가 각각 나오는지를 정리해서 if문에 넣어주는게 훨씬 간결하겠네요
T=int(input())
for _ in range(T):
x1,y1,r1,x2,y2,r2=map(int,input().split())
d=((x1-x2)**2+(y1-y2)**2)**(1/2)
sum_r=r1+r2
max_r=max(r1,r2)
min_r=min(r1,r2)
if d==0 and r1==r2:
cnt=-1
elif d>r1+r2 or d+min_r<max_r:
cnt=0
elif abs(r1-r2)==d or r1+r2==d:
cnt=1
else:
cnt=2
print(cnt)
위에서 내부/외부 얘기하면서 각 케이스를 구분한 내용을 관점만 바꿔서 다시 작성한 코드입니다. 훨씬 간결해졌죠?
복잡하게 내/외 생각할것도 없이 그냥 "어떨때 -1을 출력해야하고.. 어떨때 0,1,2를 출력해야할까?" 로 접근하는게 효율적이네요. 아마 수학내용중에 아는게나와 막 흥분했던것 같읍니다. 분명 중등수학땐 내부/외부로 배웠지만 컴퓨터 입장에선 효율성이 떨어지는 방법이네요.
'💻 Computer Science > Algorithm🐇' 카테고리의 다른 글
[python] 백준 2609 : 최대공약수와 최소공배수 (2) | 2024.01.28 |
---|---|
[python] 백준 1010 : 다리 놓기 (6) | 2024.01.24 |
[python] 백준 1072 : 게임 (4) | 2024.01.23 |
[python] 백준 1012 : 유기농 배추 (1) | 2024.01.19 |
(이상한 변호사 우영우)[python] 우영우 역삼역 '회문' 판독기 (2) | 2024.01.16 |