출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

 

수학에서는 흔한 접점 문제이다 접점이 2개이면 2, 접점이 1개면 1, 접점이 없으면 0, 접점이 무한대면 -1로 표현한다.

생각보다 꽤나 헷갈렸던 문제이다. 왜냐면 잘 기억이 안났었기 때문이다. 간단하게 머릿속으로 정리하고 다음과 같은 코드를 짜봤다:

 

import sys
import math

T = int(sys.stdin.readline())

for i in T:
    x1, y1, r1, x2, y2, r2 = map(int, sys.stdin.readline().split())
    d = math.sqrt((x1-x2)**2 + (y1-y2)**2)
    diff = math.sqrt((r1-r2)**2)
    if d > r1 + r2 or d < diff:
        print(0)
    elif d == 0 and r1 == r2:
        print(-1)
    elif d == r1 + r2 or d == diff:
        print(1)
    else:
        print(2)

하지만 런타임 에러가 뜬다.

런타임 에러가 뜨는 이유는 여러가지가 있지만, 대표적으로는 다음과 같다 (www.acmicpc.net/board/view/22980):

  1. 배열에 할당된 크기를 넘어서 접근했을 때
  2. 전역 배열의 크기가 메모리 제한을 초과할 때
  3. 지역 배열의 크기가 스택 크기 제한을 넘어갈 때
  4. 0으로 나눌 때
  5. 라이브러리에서 예외를 발생시켰을 때
  6. 재귀 호출이 너무 깊어질 때
  7. 이미 해제된 메모리를 또 참조할 때
  8. 프로그램(main 함수)이 0이 아닌 수를 반환했을 때

나의 경우에는, 이중에 어떤거인지는 확실하지 않지만, 확실한 것은 line 10 ~ 13에 있는 문제다.

if d >r1 + r2 or d < diff일 경우 print(0)을 하라고 했는데, 이는 접점이 하나도 없는 경우이다.

하지만 아래 line 12 처럼 d가 0이면서도 diff < 0 인 경우도 해당되기 때문에 두가지 모두 해당 되는 경우가 발생한다.

 

따라서 다른 방식으로 접근해줘야 한다.

d ==0  일때와, d == 0 이 아닌 경우를 나누어줘서 if문을 실행시켜야한다. 결과는 다음과 같다:

 

import sys

T = int(sys.stdin.readline())

for i in range(T):
    x1, y1, r1, x2, y2, r2 = map(int, sys.stdin.readline().split())
    d1 = ((x1 - x2)**2) + ((y1 - y2)**2)
    sum1 = (r1 + r2)**2
    diff1 = (r1 - r2)**2
    
    if d1 == 0:
        if r1 == r2:
            print(-1)
        else:
            print(0)
    else:
        if d1 == sum1 or d1 == diff1:
            print(1)
        elif d1 < sum1 and d1 > diff1:
            print(2)
        else:
            print(0)

결론은 런타임 에러 때문에 애먹었던 문제이다.