본문 바로가기

백준

1004)어린 왕자

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


시작점에서 도착점까지 행성계를 진입/이탈 하는 최소 횟수를 구해야 한다.


되게 어려워 보이지만 잘 관찰해보면 점이 원 내부에 있는가 외부에 있는가에 따라 진입/이탈 횟수가 결정됨을 알 수 있다.



위 그림에서 왼쪽 빨간 점은 아주 큰 행성계 하나에만 포함되어 있고


오른쪽 빨간 점은 두 개의 행성계에 포함되어 있다.


각 점이 행성계에 몇 번 포함됬냐에 따라 진입/이탈 횟수를 쉽게 알 수 있다.


어떤 점이 원 안에 포함됬는 지 여부를 확인 하려면 P(x0, y0)을 C : (x-a)^2 + (y-b)^2에 대입했을 때


C(x0,y0) > r^2이면 점이 원 바깥에 있고 C(x0,y0) < r^2이면 점은 원 안에 있다.



그림처럼 두 점이 같은 행성계에 포함되면 진입/이탈을 할 필요가 없다.


두 점이 각 원에 대해 포함 여부를 파악하고 각 포함 여부를 XOR 연산해 참인 경우를 세어 출력하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<stdio.h>
 
typedef struct _Point {
    int x;
    int y;
}Point;
 
typedef struct _Circle {
    int x;
    int y;
    int r;
}Circle;
 
typedef enum _BOOL {
    TRUE = 1, FALSE = 0
}Bool;
 
int power(int a) {
    return a*a;
}
 
Bool isInsideCircle(Circle circle, Point point) {
    if (power(point.x - circle.x) + power(point.y - circle.y) > power(circle.r)) return FALSE;
    else return TRUE;
}
 
int main() {
    int n, m;
    Point point[2];
    Circle circle[50];
    Bool isInside[2][50= {FALSE};
    int count;
 
    scanf("%d",&n);
    for (int i = 0; i < n;i++) {
        for (int j = 0; j < 2;j++scanf("%d %d"&point[j].x, &point[j].y);
        scanf("%d",&m);
        
        for (int j = 0; j < m;j++) {
            scanf("%d %d %d",&circle[j].x, &circle[j].y, &circle[j].r);
        }
 
        for (int j = 0; j < 2;j++) {
            for (int k = 0; k < m;k++) {
                isInside[j][k] = isInsideCircle(circle[k], point[j]);
            }
        }
        
        count = 0;
        for (int j = 0; j < m;j++) {
            if (isInside[0][j] ^ isInside[1][j]) count++;
        }
 
        printf("%d\n",count);
    }
 
    return 0;
}
cs


'백준' 카테고리의 다른 글

1158)조세퍼스 문제  (0) 2019.03.04
10824)네 수  (0) 2019.03.03
14910)오르막  (0) 2019.02.26
2991)사나운 개  (0) 2019.02.24
2210)숫자판 점프  (0) 2019.02.23