파게로그

[백준 1002번] 터렛, 두 원의 교점의 개수 본문

콤퓨타 왕왕기초/PS

[백준 1002번] 터렛, 두 원의 교점의 개수

파게 2020. 10. 30. 18:53

문제 링크: 1002번 터렛

https://www.acmicpc.net/problem/1002

 

반지름이 r1, r2인 두 원은 다음과 같은 위치 관계를 가질 수 있다.

 

1. 서로 다른 두 점에서 만난다.

|r2-r1| < d < r2+r1

 

2. 한 점에서 접한다.

2-1. 외접

r1+r2 = d

 

2-2. 내접

|r2-r1| = d

 

3. 만나지 않는다.

3-1. 한 원이 다른 원의 외부에 있을 경우

d > r1+r2

 

3-2. 한 원이 다른 원의 내부에 있을 경우(반지름이 다른 동심원 포함)

d < |r2-r1|

 

4. 무수히 많은 점에서 만난다(반지름이 같은 동심원).

두 원의 중심이 같고, r1 = r2

 

그런데 이 문제를 풀 때, d를 구할 때에는 점과 점 사이의 거리 공식을 이용해야 하고, 이는 기본적으로 피타고라스 정리를 이용한 것이다. 곧, d를 구하기 위해서는 제곱근을 이용할 수밖에 없다.

이는 실수 자료형을 이용하게 하고, 곧 코드는 오차로 인한 오답의 위험성을 내포하게 된다. 이를 방지하고자 d와 r1+r2, r1-r2를 비교하는 것이 아니라 d^2과 (r1+r2)^2, (r1-r2)^2을 비교하여 정수형으로만 문제를 풀 수 있다.

 

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int test = Integer.parseInt(br.readLine());
        while (test-- > 0) {
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            int x1 = Integer.parseInt(st.nextToken());
            int y1 = Integer.parseInt(st.nextToken());
            int r1 = Integer.parseInt(st.nextToken());
            int x2 = Integer.parseInt(st.nextToken());
            int y2 = Integer.parseInt(st.nextToken());
            int r2 = Integer.parseInt(st.nextToken());

            int sqd = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);

            int rs = (r1 + r2) * (r1 + r2);
            int rd = (r1 - r2) * (r1 - r2);

            if (x1 == x2 && y1 == y2 && r1 == r2) {
                sb.append(-1);
            } else if (sqd > rs) {
                sb.append(0);
            } else if (sqd == rs) {
                sb.append(1);
            } else if (rd < sqd) {
                sb.append(2);
            } else if (sqd == rd) {
                sb.append(1);
            } else {
                sb.append(0);
            }

            sb.append('\n');
        }

        System.out.print(sb);
    }
}

 

참고로, 아래 코드는 내가 PS를 처음 시작했을 때 짠 코드로서 오차를 고려하지 않았다. 통과는 하지만, 좋은 코드라고 할 수는 없다.

 

#include <iostream>
#include <cmath>
using namespace std;

int main(void) {
    int x1, y1, r1, x2, y2, r2;
    double d;
    int cases; cin >> cases;
    
    for (int i = 0; i < cases; i++) {
        cin >> x1 >> y1 >> r1 >> x2 >> y2 >> r2;
        d = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
        int rdiff = r1 - r2 > 0 ? (r1-r2) : (-1) * (r1-r2);

        if (d == 0 && r1 == r2) {
            cout << -1;
        } else if (d > r1 + r2) || d < rdiff) {
            cout << 0;
        } else if (d == r1 + r2) || d == rdiff) {
            cout << 1;
        } else if (d < r1 + r2) {
            cout << 2;
        }
        cout << '\n';
    }
    
    return 0;
}

'콤퓨타 왕왕기초 > PS' 카테고리의 다른 글

[백준 10870번] 피보나치  (0) 2020.10.30
[백준 10872번] 팩토리얼  (0) 2020.10.30
[백준 3053번] 택시 기하학  (0) 2020.10.30
[백준 3009번] 네 번째 점  (0) 2020.10.30
[백준 9020번] 골드바흐의 추측  (0) 2020.10.30
Comments