반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. Convex Hull


컨벡스 헐을 이용하여 문제를 풀 수 있는 기본적인 문제이다.


http://www.crocus.co.kr/1288?category=209527


위의 링크를 참고하여 컨벡스 헐 알고리즘을 이해하고 문제를 풀어보자.






소스 코드 : 


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
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
 
#define MAX 100002
 
using namespace std;
 
typedef long long ll;
 
struct Point {
    int x, y;
    int p, q;
    Point(int x1 = 0int y1 = 0) : x(x1), y(y1), p(1), q(0) {}
};
 
bool comp1(const Point &A, const Point &B) {
    if (A.y != B.y)
        return A.y < B.y;
 
    return A.x < B.x;
}
bool comp(const Point &A, const Point &B) {
    if (1LL * A.q * B.p != 1LL * A.p*B.q)
        return 1LL * A.q * B.p < 1LL * A.p*B.q;
 
    if (A.y != B.y)
        return A.y < B.y;
 
    return A.x < B.x;
}
 
ll ccw(const Point &A, const Point &B, const Point &C) {
    return 1LL * (A.x*B.y + B.x*C.y + C.x*A.y - B.x*A.y - C.x*B.y - A.x*C.y);
}
 
Point p[MAX];
 
int main() {
    int n;
    scanf("%d"&n);
 
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d %d"&x, &y);
 
        p[i] = Point(x, y);
    }
 
    sort(p, p + n, comp1);
 
    for (int i = 1; i < n; i++) {
        p[i].p = p[i].x - p[0].x;
        p[i].q = p[i].y - p[0].y;
    }
 
    sort(p + 1, p + n, comp);
 
    stack<int> s;
 
    s.push(0);
    s.push(1);
 
    int next = 2;
 
    while (next < n) {
        while (s.size() >= 2) {
            int first, second;
            second = s.top();
            s.pop();
            first = s.top();
 
            if (ccw(p[first], p[second], p[next]) > 0) {
                s.push(second);
                break;
            }
        }
 
        s.push(next++);
    }
 
    printf("%d", s.size());
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus





STL 사용하지 않고 Convex Hull 구현하고 문제 풀기



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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include <iostream>
#include <cstdio>
#include <algorithm>
 
#define MAX 100002
 
using namespace std;
 
typedef long long ll;
 
struct Point {
    int x, y;
    int p, q;
    Point(int x1 = 0int y1 = 0) : x(x1), y(y1), p(1), q(0) {}
};
 
ll ccw(const Point &A, const Point &B, const Point &C) {
    return 1LL * (A.x*B.y + B.x*C.y + C.x*A.y - B.x*A.y - C.x*B.y - A.x*C.y);
}
 
Point p[MAX];
Point tmp[MAX];
 
bool comp1(const Point &A, const Point &B) {
    if (A.y != B.y)
        return A.y < B.y;
 
    return A.x < B.x;
}
bool comp(const Point &A, const Point &B) {
    if (1LL * A.q * B.p != 1LL * A.p*B.q)
        return 1LL * A.q * B.p < 1LL * A.p*B.q;
 
    if (A.y != B.y)
        return A.y < B.y;
 
    return A.x < B.x;
}
 
void mergeSortComp1(int start, int end) {
    if (start < end) {
        int mid = (start + end) >> 1;
 
        mergeSortComp1(start, mid);
        mergeSortComp1(mid + 1, end);
 
        int left = start, right = mid + 1;
        int idx = start;
 
        while (left <= mid || right <= end) {
            if (right > end || (left <= mid && comp(p[left], p[right]))) {
                tmp[idx++= p[left++];
            }
            else
                tmp[idx++= p[right++];
        }
        
        for (int i = start; i <= end; i++)
            p[i] = tmp[i];
    }
}
void mergeSortComp(int start, int end) {
    if (start < end) {
        int mid = (start + end) >> 1;
 
        mergeSortComp(start, mid);
        mergeSortComp(mid + 1, end);
 
        int left = start, right = mid + 1;
        int idx = start;
 
        while (left <= mid || right <= end) {
            if (right > end || (left <= mid && comp(p[left], p[right]))) {
                tmp[idx++= p[left++];
            }
            else
                tmp[idx++= p[right++];
        }
 
        for (int i = start; i <= end; i++)
            p[i] = tmp[i];
    }
}
 
 
class stack {
public:
    int capacity, sz;
    int *st;
 
    stack() {
        capacity = 8;
        sz = 0;
        st = new int[capacity];
    }
    ~stack() { delete[] st; }
 
    void push(int val) {
        if (capacity == sz) {
            capacity *= 2;
            int *tmp = new int[capacity];
            for (register int i = 0; i < sz; i++)
                tmp[i] = st[i];
            delete[] st;
            st = tmp;
        }
        st[sz++= val;
    }
    int top() {
        return st[sz - 1];
    }
    void pop() {
        sz--;
    }
    int size() { return sz; }
    bool empty() { return !sz; }
    void clear() {
        delete[] st;
        capacity = 8;
        sz = 0;
        st = new int[capacity];
    }
};
 
stack s;
int main() {
 
        int n;
        scanf("%d"&n);
 
        for (int i = 0; i < n; i++) {
            int x, y;
            scanf("%d %d"&x, &y);
 
            p[i] = Point(x, y);
        }
 
        mergeSortComp1(0, n - 1);
 
        for (int i = 1; i < n; i++) {
            p[i].p = p[i].x - p[0].x;
            p[i].q = p[i].y - p[0].y;
        }
 
        mergeSortComp(1, n - 1);
 
 
        s.push(0);
        s.push(1);
 
        int next = 2;
 
        while (next < n) {
            while (s.size() >= 2) {
                int first, second;
                second = s.top();
                s.pop();
                first = s.top();
 
                if (ccw(p[first], p[second], p[next]) > 0) {
                    s.push(second);
                    break;
                }
            }
 
            s.push(next++);
        }
 
        printf("%d\n", s.size());
 
    return 0;
}
 
 
cs


반응형

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

[2591번] 숫자 카드  (0) 2018.06.30
[13326번] Diameter  (0) 2018.06.28
[13326번] Diameter  (0) 2018.06.21
[15729번] 방탈출  (0) 2018.05.22
[1933번] 스카이라인  (2) 2018.05.11