상당히 고전했던 문제다.
다 풀었다고 생각했는데 틀리고, 수정했는데 또 틀리는 그런 형태의 문제
구현 자체에 대한 문제도 있었지만,
아무래도 문제 자체가 수학, 그중에서도 기하학에 대한 개념이 있어야 했기에 더 어려움을 가졌던 것 같다.
우선 이 문제를 알기 위해서는 반드시 알아야 할 것이 "원의 내접과 외접, 그리고 위치 관계"에 대한 부분이다.
자세한 부분은 일단 다음 사이트를 참조하는 것이 최고다.
공부 참조 출처: https://mathbang.net/101
두 원의 위치관계, 내접, 외접
위치관계 또 나오네요. 이번에는 두 원의 위치관계에요. 위치관계 마지막이니까 정신 바짝 차리고 따라오세요. 원과 직선의 위치관계, 원의 할선과 접선, 접점에서 했던 것처럼 두 원이 어떤 관
mathbang.net
위의 내용을 알기 전에는 다음과 같이 코딩을 하였다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 시도1
test_case = int (input()) # 테스트 케이스 갯수
for i in range (test_case):
x1, y1, r1, x2, y2, r2 = list(map(int , input().split())) # 조규현 좌표(x1, y1)과 백승환 좌표(x2, y2)와 류재명과의 거리 r1, r2
distance = ((x2 - x1) * * 2 + (y2 - y1) * * 2 ) * * 0. 5
if distance = = 0 :
if r1 ! = r2: # 류가 있을 수 있는 위치가 존재하지 않는다.
print (0 )
else : # 류가 있을 수 있는 위치는 r1(=r2)를 반지름으로 가진 원의 위치 중 어디든 가능하다.
print (- 1 )
else :
if (r1+ r2) = = distance: # r1과r2가 만나는 지점 1군데에서 류가 있을 수 있다.
print (1 )
elif (r1+ r2) > distance: # r1+r2가 더 크다면 distance 직선기준으로 아래 위로 총 2군데 발생할 수 있다.
print (2 )
else :
pass
cs
하지만 계속 백준에서 틀렸다고 나왔고, 그래서 결국 기억을 짜내서 원의 내접과 외접이 생각나서 인터넷 검색을 통해서 조건을 알게 되었다.
조건을 정리하자면 다음과 같다.
계산한 거리는 반지름으로 r1, r2(r1 > r2)를 가지고, 두 중심간의 거리를 d라고 가정할 때 두 점에서 만나는 경우 d != 0 and r1 - r2 < d < r1 + r2 한 점에서 만나는 경우 d != 0 and { r1+r2 = d (외접) r1-r2 = d(내접)} 한 점에서도 만나지 않을 경우 d = 0 and r1 - r2 != 0 d != 0 and r1 + r2 > d 무수히 많은 점에서 만날 경우 d = 0 and r1 - r2 = 0
이런 조건들을 통해서 다시 만든 코드는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 시도2
test_case = int (input()) # 테스트 케이스 갯수
for i in range (test_case):
x1, y1, r1, x2, y2, r2 = list(map(int , input().split())) # 조규현 좌표(x1, y1)과 백승환 좌표(x2, y2)와 류재명과의 거리 r1, r2
distance = ((x2 - x1) * * 2 + (y2 - y1) * * 2 ) * * 0. 5
if distance = = 0 :
if r1 ! = r2: # 류가 있을 수 있는 위치가 존재하지 않는다.
print (0 )
else : # 류가 있을 수 있는 위치는 r1(=r2)를 반지름으로 가진 원의 위치 중 어디든 가능하다.
print (- 1 )
else :
if (r1+ r2) = = distance or abs(r1- r2) = = distance: # r1과r2가 만나는 지점 1군데에서 류가 있을 수 있다.
print (1 )
elif (r1+ r2) > distance and abs(r1- r2) < distance: # r1+r2가 더 크다면 distance 직선기준으로 아래 위로 총 2군데 발생할 수 있다.
print (2 )
else :
pass
cs
문제는 위의 코드도 틀렸다는 점이다.
틀린 이유는 else문 내의 else문 때문이다.
else문의 경우 pass가 아닌 0을 출력해야 하기 때문이다. 이유는, if-elif를 통해서 찾을 수 있는 경우들을 제외하면 점을 가질 수 없기 때문이고, 점이 없을 때는 0을 출력해야 하기 때문이다.
(이 틀린 부분을 찾기 위해서 상당히 오랜 시간이 걸렸다....)
결론적으로 제대로 된 코드는 다음과 같다!!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
test_case = int (input()) # 테스트 케이스 갯수
for i in range (test_case):
x1, y1, r1, x2, y2, r2 = list(map(int , input().split())) # 조규현 좌표(x1, y1)과 백승환 좌표(x2, y2)와 류재명과의 거리 r1, r2
distance = ((x2 - x1) * * 2 + (y2 - y1) * * 2 ) * * 0. 5
if distance = = 0 :
if r1 ! = r2: # 류가 있을 수 있는 위치가 존재하지 않는다.
print (0 )
else : # 류가 있을 수 있는 위치는 r1(=r2)를 반지름으로 가진 원의 위치 중 어디든 가능하다.
print (- 1 )
else :
if (r1+ r2) = = distance or abs(r1- r2) = = distance: # r1과r2가 만나는 지점 1군데에서 류가 있을 수 있다.
print (1 )
elif (r1+ r2) > distance and abs(r1- r2) < distance: # r1+r2가 더 크다면 distance 직선기준으로 아래 위로 총 2군데 발생할 수 있다.
print (2 )
else :
print (0 )
cs
상당히 오래 걸린 문제이고, 결국에는 원의 내접과 외접에 대해서 알아야 했던 문제이다.
보아하니 원의 내접과 외접은 중학교 수준의 문제라는 것 같다...
문제 출처: https://www.acmicpc.net/problem/1002
1002번: 터렛
각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.
www.acmicpc.net