https://www.acmicpc.net/problem/1002
1002번: 터렛
각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.
www.acmicpc.net

풀이
처음 문제를 봤을 때 이해가 잘 안갔다..
검색을 하고나서야 이해가 갔다. 하나씩 이해해보겠다.
문제에선 두 개의 터렛 x, y 좌표와 류재명과의 r1, r2가 제공된다.
그렇다면 x, y를 기준으로 r1, r2의 반지름을 가진 원을 그릴 수 있다.
두 개의 원이 그러졌다면 A 터렛의 원과 B 터렛의 원의 접점 개수를 구하면 된다.
두 개의 원을 그렸을 때 생기는 접점의 개수에 대한 경우의 수는 몇 개일까?

위 그림처럼 여러가지가 있겠지만 4가지로 나눌 수 있다.
1.두 개의 접점이 생기는 경우
2. 한 개의 접점이 생기는 경우
3. 겹치지 않는 경우
4. 두 개의 원이 겹치는 경우
1. 두 개의 접점이 생기는 경우
: 그림 (1)
else if (dist > Math.pow(r2-r1,2) && dist < Math.pow(r1+r2,2)) { arr[i] = 2; }
2. 한 개의 접점이 생기는 경우
: 그림 (2), (3)
else if (Math.pow(r2-r1,2) == dist || Math.pow(r2+r1,2) == dist) { arr[i] = 1; }
3. 겹치지 않는 경우
: 그림 (4), (5), (6)
else if (Math.pow(r1+r2,2) < dist || Math.pow(r2-r1,2) > dist || dist == 0) { arr[i] = 0; }
4. 두 개의 원이 겹치는 경우
if (dist == 0 && r1 == r2) { arr[i] = -1; }
여기서 나오는 dist 변수는 두 개의 원 중점의 거리이다.
대부분의 풀이를 보면 double 형 또는 float 형으로 변수를 선언해서 Math.sqrt 를 사용했다.
double dist = Math.sqrt(Math.pow(x2-x1, 2) + Math.pow(y2-y1, 2));
하지만 이렇게 되면 정확한 값이 아니다. if-else 문을 통해서 간단한 연산을 해보면 쉽게 이해할 수 있다.
import java.io.*; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws IOException { double a = 0.1; double b = 0.2; double c = 0.3; if(a + b == c) System.out.print("참입니다."); else System.out.print("거짓입니다."); } } // 거짓입니다.
이러한 이유로 필자는 Math.sqrt 를 사용하지않고 Math.pow(x2-x1, 2) + Math.pow(y2-y1, 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)); StringTokenizer st; int T = Integer.parseInt(br.readLine()); int[] arr = new int[T]; for (int i=0; i<T; 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()); // 두 개의 원 중점의 거리 int dist = (int)(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); // 두 개의 원이 겹치는 경우 if (dist == 0 && r1 == r2) { arr[i] = -1; } // 두 개의 접점이 생기는 경우 else if (dist > Math.pow(r2-r1,2) && dist < Math.pow(r1+r2,2)) { arr[i] = 2; } // 한 개의 접점이 생기는 경우 else if (Math.pow(r2-r1,2) == dist || Math.pow(r2+r1,2) == dist) { arr[i] = 1; } // 겹치지 않는 경우 else if (Math.pow(r1+r2,2) < dist || Math.pow(r2-r1,2) > dist || dist == 0) { arr[i] = 0; } } for (int num : arr) { System.out.println(num); } } }
'알고리즘 > 구현 & 그리디 & 브루트포스' 카테고리의 다른 글
[백준]JAVA - 11399번: ATM (0) | 2022.10.20 |
---|---|
[백준]JAVA - 1052번: 물병 (0) | 2022.10.08 |
[백준]JAVA - 1652번: 누울 자리를 찾아라 (0) | 2022.09.26 |
[백준]JAVA - 1085번: 직사각형에서 탈출 (0) | 2022.09.26 |
[백준]JAVA - 1475번: 방 번호 (0) | 2022.09.22 |