potatoo 2022. 12. 22. 09:56
728x90

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

 

1002번: 터렛

각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.

www.acmicpc.net

이 문제는 경우를 따지는 것이 조금 어려웠다.

처음에는 접근 방법을 어떤 식으로 해야하나 고민하면서 그림을 여러 차례 그려보면서 조금씩 이해했고, 반례를 찾기위해 저번처럼 질문 게시판의 반례들을 사용해보면서 경우를 찾아 냈다.

 

원리는 정리해보면 간단하다. 두 좌표지점에서 그리는 각각의 원이 접해서 생기는 점의 갯수를 구하는 것이다.

경우는 접하지 않는 경우, 접하는 경우, 원 안에 원이 포함되어 접하는 경우, 원 안에 원이 포함된 경우, 원이 같은 경우로 5개의 경우가 있다.

그래서 간단히 생각하면 조건문으로 조건식을 경우의 수를 따져서 세우는 문제이다.

 

처음에는 따로 클래스를 정의해서 하려고 했었는데 굳이 그럴 필요 없을 것 같아서 클래스는 지우고 메인에서 처리했다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class b1002 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int count = Integer.parseInt(br.readLine());
        StringTokenizer st;
        for(int i=0; i<count; i++){
            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());
            double x = Math.abs(x1-x2);
            double y = Math.abs(y1-y2);
            double distance = Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
            int maxR = Math.max(r1,r2);
            int minR = Math.min(r1,r2);
            if(distance==r1+r2){
                System.out.println(1);
            }//둘이 딱 한점에서 접할 때
            else if (x1==x2 && y1==y2 && r1==r2) {
                System.out.println(-1);
            }//둘이 같은 원일 때
            else {
                if(distance<r1+r2){
                    if(distance<maxR-minR){
                        System.out.println(0);//둘의 거리 차가 반지름 차보다 작으면 원 안에 원이 존재한다.
                    } else if (distance==maxR-minR) {
                        System.out.println(1);//원 안에 원이 있을 때 둘이 접하는 경우
                    } else System.out.println(2);//그 외는 모두 겹치는 두 원
                }else System.out.println(0);//같은 원도 아니고 거리도 멀면 아예 접하지 않음
            }
        }
    }
}

처음 좌표값과 반지름을 입력받아 정의하는 부분이 조금 더럽긴 하지만 그냥 사용했다....

일단 위 코드처럼 좌표간의 거리를 구하고 거리와 반지름간의 관계를 이용해서 위에 설명한 5가지 경우의 수를 계산하였다.

한 점에서 접하는 경우는 두 반지름 길이의 합과 같고, 좌표와 반지름이 다 같은 경우는 -1을 반환한다.

그리고 이제 중요한 부분은 거리와 두 반지름 합의 크기가 다를 때이다.

거리가 두 반지름의 합보다 작을 때가 이 문제의 제일 중요한 풀이 과정인것 같다.

그래서 이 경우에 큰 반지름에서 작은 반지름을 뺀 값이 크다면 원 안에 원이 들어있는 경우이다.

또 원 안에 원이 있는 경우 중에 큰 반지름에서 작은 반지름을 뺀 값이 거리와 같다면 원안의 원이 바깥원과 접하는 것이다.

그 외의 경우는 모두 겹치는 두 원이 있는 것이므로 2개의 접점이 있다.

728x90