반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. 라인 스위핑

2. Map


이 문제는 아직 내 힘으로는 풀기가 힘들어 다른 사람들의 풀이를 참고하여 공부한 내용이다.


이 소스 코드의 동작은 다음과 같다.


1. 모든 x,y 값을 받아내고, x에 대해 정렬을 한다.

2. 정렬 후 가장 작은 x값 두 점의 거리를 구한다. 이 두 점간의 거리를 최단 거리라고 처음에 가정한다.

2. 이제 for문을 통해 한 점을 잡고, 한 점과 last(0부터 시작)점을 잡아 두점간의 x거리를 구하는데

이 x간의 거리가 최단 거리보다 크면 map에서 지워준다.(라인 스위핑)


3. 최단 거리보다 짧은 거리가 나온 점이 있다면 break를 해주고(현재 이 점은 최단 거리보다 거리가 짧게 나올 수 있는 후보이다.)

그 점을 기준으로 lower_bound, upper_bound를 이용하여 이 점을 기준으로 

현재 최단 거리의 길이를 가지는 사각형 내부의 모든 점의 최솟값을 조사한다.


4. 최솟값을 찾아내고, 현재 점 i를 map에 추가시켜주며 반복한다.



아직 Line Sweeping은 조금 어렵기도하고, 더 공부해야 될 부분인 것 같다.

참고로 이 문제를 Divide And Conquer 방법으로도 풀 수 있다고 한다.






소스 코드 : 


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
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
 
#define inf 100000000
 
using namespace std;
 
typedef pair<intint> pii;
 
map<pii, int> mp;
 
double getDist(pii a, pii b)
{
    int x = a.first - b.first;
    int y = a.second - b.second;
 
    return (double)(x*+ y*y);
}
 
int main()
{
    int n;
    scanf("%d"&n);
 
    vector<pii> vc;
 
    for (int i = 0; i < n; i++)
    {
        int x, y;
        scanf("%d %d"&x, &y);
 
        vc.push_back({ x,y });
    }
 
    // x에 대해 정렬
    sort(vc.begin(), vc.end());
 
    // 처음 두 값 map에 추가(y, x 순서)
    mp[{vc[0].second, vc[0].first}] = 1;
    mp[{vc[1].second, vc[1].first}] = 1;
 
    // 최솟값 초기화
    double ans = getDist(vc[0], vc[1]);
 
    int last = 0;
 
    for (int i = 2; i < n; i++)
    {
        // while문은 최솟값보다 x간의 거리가 더 큰 것을 제거하는 과정
        // x간의 거리가 최솟값 보다 더 크면 y값을 비교할 필요가 없다.
        while (last < i)
        {
            // i > last
            int dx = vc[i].first - vc[last].first;
 
            // 최솟값이 더 크거나 같으면 break;(검사여지 없음)
            if (dx * dx <= ans)
                break;
 
            // 최솟값 보다 더 큰 last에 해당하는 mp값 제거
            mp.erase({ vc[last].second, vc[last].first });
            last++;
        }
 
        // ans의 실제 거리
        int limit = sqrt(ans);
 
        // y좌표를 봤을 때 현재 알고있는 최솟값 기준으로 답일 수 있는 영역 설정
        auto lo = mp.lower_bound({ vc[i].second - limit, -inf });
        auto up = mp.upper_bound({ vc[i].second + limit,  inf });
 
        // 그 영역 내에서 최솟값
        for (auto it = lo; it != up; it++)
            ans = min(ans, getDist({ it->first.second, it->first.first }, vc[i]));
 
        // map에 추가
        mp[{vc[i].second, vc[i].first}] = 1;
    }
 
    printf("%d", (int)ans);
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[9291번] 스도쿠 채점  (2) 2017.04.22
[1992번] 쿼드트리  (0) 2017.04.22
[11945번] 뜨거운 붕어빵  (0) 2017.04.21
[3793번] Common Subsequence  (5) 2017.04.21
[2941번] 크로아티아 알파벳  (0) 2017.04.21