본문 바로가기

알고리즘/Baekjoon

js. [1002]

[1. 문제 설명]

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


[2. 풀이 접근]

중심 좌표가 있고, 거리가 있다 => 중심 좌표로 부터 동일한 거리 => 원

두 개의 원이 있고, 이 원의 관계성을 이용하여 해의 개수를 판별 한다.

 

두 원의 중심 간의 거리의 제곱을 d 라하면 (정수 값으로 비교하기 위함)

1) 두 원의 중심이 같을 때

    => 두 원의 반지름이 같으면, 해의 개수가 무한대 (특수해)

    => 두 원의 반지름이 다르면, 해의 개수 없음

2) 작은 원의 중심이 큰 원 바깥에 있을 때
    => 두 원이 만나지 않음, 해의 개수 없음           (d > r1+r2)

    => 두 원이 접함, 해의 개수는 1개                    (d == r1+r2)

    => 두 원이 두점에서 교차 함, 해의 개수는 2개 (d < r1+r2)

3) 작은 원의 중심이 큰 원 안쪽에 있을 때 
    => 두 원이 만나지 않음,    (d < abs(r2 - r1))

    => 두 원이 접합,               (d = abs(r2 - r1))
    => 두 원이 두점에서 교차, (d > abs(r2 - r1))

 

단, d 는 사실 sqrt(d2) 이므로, 정수 비교를 위해 수식을 적절히 변형 후,

제곱하여 정수 단위 비교를 하는 편이 적절히 보임 

 

그림으로 보면 아래와 같다.

1)

 

2) 

 

3) 

 


[3. 코드]

const fs = require("fs");
const process = require("process");

const inputs = fs.readFileSync(process.stdin.fd).toString().trim().split("\n");
const N = Number(inputs[0]);

const result = [];
for (let idx=1; idx<=N; idx++) {
    const input = inputs[idx].split(" ").map(Number);

    let [x1, y1, r1] = [input[0], input[1], input[2]];
    let [x2, y2, r2] = [input[3], input[4], input[5]];

    if (r1 > r2) {
        // swap 할 때 주의해야 함.
        // 아래는 원하는 대로 swap 되지 않음.
        // [x1, y1, r1] = [x2, y2, r2]
        [x1, y1, r1, x2, y2, r2] = [x2, y2, r2, x1, y1, r1];
    }

    // r1 < r2
    // 항상 r2 가 더 큰 원이고, 
    // r2 에 해당하는 원의 중심은 원점으로 가정하겠다.
    // 이에 맞춰 r1 에 해당하는 원의 중심을 옮긴다.
    x1 -= x2;
    y1 -= y2;
    x2 = 0;
    y2 = 0;

    const d_sq = (x1**2 + y1**2); // 두 원의 중심 간의 거리의 제곱
    const s2 = (r1+r2) ** 2;      // 반지름 합의 제곱
    const s3 = (r2-r1) ** 2;      // 반지름 차의 제곱

    if (d_sq == 0) { // 중심이 같을 때,
        if (r1 == r2) { // 반지름이 같음, 무한한 점이 겹침
            result.push(-1);
        } else {        // 반지름이 다름, 겹치는 구간 없음
            result.push(0);
        }
    } else if (d_sq > r2**2) { // 작은 원의 중심이 큰 원의 외부에 있을 때,
        if (d_sq == s2) {       // 두 원이 접할 때
            result.push(1);
        } else if (d_sq > s2) { // 두 원이 만나지 않음
            result.push(0);
        } else {                // 두 원이 두 점에서 교차함
            result.push(2);
        }
    } else { // 작은 원의 중심이 큰 원의 내부에 있을 때,
        if (d_sq == s3) {       // 두 원이 접함
            result.push(1);
        } else if (d_sq < s3) { // 두 원이 만나지 않음
            result.push(0);
        } else {                // 두 원이 두 점에서 교차함
            result.push(2);
        }
    }
}

// 한번에 출력하는 것이 시간에서 이득을 볼 수 있다.
// 기본적으론 출력 버퍼를 매번 flush 하기 때문이다.
console.log(result.join("\n"));

'알고리즘 > Baekjoon' 카테고리의 다른 글

... [1762]  (0) 2025.06.10
mo`s. [13548]  (0) 2025.06.04
제곱근 분할법. [13546]  (0) 2025.06.03
차분 배열 [19551]  (0) 2025.05.21
라빈-카프 [3033]  (1) 2025.05.17