(구) 자료/Baekjoon Online Judge

2412 / 암벽 등반

뜐뜐뜐 2018. 7. 10. 20:01
시간 제한메모리 제한제출정답맞은 사람정답 비율
2 초128 MB87321014424.324%

문제

어떤 암벽에 n(1≤n≤50,000)개의 홈이 파져 있다. 각각의 홈의 좌표는 (x, y)와 같이 표현되는데, |a-x|≤2이고 |b-y|≤2이면 (x, y)에서 (a, b)로 이동할 수 있다. 이와 같이 홈들을 이용하여 이동하면서 y=T(1≤T≤200,000)일 때까지, 즉 암벽의 정상까지 오르려고 한다.

현재 당신이 있는 위치는 (0, 0)이다. 이 위치에서 시작하여 이동 회수를 최소로 하면서 정상에 오르려고 한다. 정상에 오를 때의 x좌표는 아무 것이나 되어도 상관이 없다.

입력

첫째 줄에 n, T가 주어진다. 다음 n개의 줄에는 각 점의 x, y좌표가 주어진다. 두 좌표는 모두 0이상이며, x좌표는 1,000,000이하, y좌표는 T이하이다. 입력에 현재 위치인 (0, 0)은 주어지지 않는다.

출력

첫째 줄에 최소 이동 회수를 출력한다. 만약, 정상에 오를 수 없으면 -1을 출력한다.




BFS + 응용문제.


길이가 4 x 4인 정 사각형의 각 대각선의 교점이 현재 위치가 된다고 생각하면 된다.


즉, 자신의 위치를 중심으로 사각형을 그렸을 때, 그 내부의 모든 점을 Queue에 넣으면서 위로 올라가면 된다.


큐에 넣을 때 주의할 점은, 이미 방문한 점은 더 적은 횟수로 이미 도착할 수 있는 점이기 때문에 visit처리를 해주어야 중복을 막을 수 있다는 점이다.


핵심은


1. 입력 받은 모든 점들을 y좌표의 오름차순(같은 경우 x의 오름차순 정렬)으로 먼저 정렬 해주어야 함

2. 자신의 인덱스를 기준으로 상, 하, 좌, 우 거리가 2인 모든점을 탐색해야 하므로 큐에 자신의 인덱스를 같이 넣어주고 양 방향으로 탐색해주어야 시간초과가 나지 않음.

3. 오름차순으로 정렬했기 때문에 범위가 사각형을 벗어나는 순간 그 이후 모든 점은 사각형의 범위 밖이므로 탐색하며 큐에 넣을 필요가 없음.


[Code]

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<utility>
#include<algorithm>
#include<queue>
#define P pair<int,int>
#define PP pair<P,P>
#define mp(a,b) make_pair(a,b)
using namespace std;
 
int n, t, res;
P arr[50001];
bool visit[50001];
 
int bfs();
 
bool cmp(P a, P b) {
    if (a.second == b.second) return (a.first < b.first);
    else return (a.second < b.second);
}
 
int main() {
 
    scanf("%d%d"&n, &t);
 
    for (int i = 0; i < n; i++
        scanf("%d%d"&arr[i].first, &arr[i].second);
    
    sort(arr, arr + n, cmp);
 
    printf("%d\n", bfs());
 
    return 0;
}
 
int bfs() {
    queue<PP> Q;
    Q.push(mp(mp(00), mp(0,0)));
 
    while (!Q.empty()) {
        int cx = Q.front().first.first;
        int cy = Q.front().first.second;
        int cnt = Q.front().second.first;
        int idx = Q.front().second.second;
        Q.pop();
 
        if (cy == t) return cnt;
 
        for (int i = idx; i < n; i++) {
            int nx = arr[i].first;
            int ny = arr[i].second;
            if (!visit[i]) {
                if ((abs(cx - nx) <= 2&& (abs(cy - ny) <= 2)) {
                    visit[i] = true;
                    Q.push(mp(mp(nx, ny), mp(cnt + 1, i)));
                }
                else if ((abs(cx - nx) > 2&& (abs(cy - ny) > 2)) break;
            }
        }
 
        for (int i = idx; i >= 0; i--) {
            int nx = arr[i].first;
            int ny = arr[i].second;
            if (!visit[i]) {
                if ((abs(cx - nx) <= 2&& (abs(cy - ny) <= 2)) {
                    visit[i] = true;
                    Q.push(mp(mp(nx, ny), mp(cnt + 1, i)));
                }
                else if ((abs(cx - nx) > 2&& (abs(cy - ny) > 2)) break;
            }
        }
 
    }
 
    return -1;
}
cs