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
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <set>
#include <cmath>
#include <limits>
#include <cstring>
#include <string>
using namespace std;
typedef long long ll;
 
struct point {
    ll x, y;
    ll p = 0, q = 0;
};
 
bool cmp2(point& a, point& b) {
    if (1LL * a.p * b.q != 1LL * a.q * b.p) return 1LL * a.q * b.p < 1LL * a.p * b.q;
    if (a.x != b.x) return a.x > b.x;
    return a.y < b.y;
}
 
bool cmp(point& a, point& b) {
    if (a.x != b.x) return a.x < b.x;
    return a.y < b.y;
}
 
ll ccw(point& a, point& b, point& c) {
    return 1LL * (b.x - a.x) * (c.y - a.y) - 1LL * (b.y - a.y) * (c.x - a.x);
}
 
int N, i, x, y;
point arr[100000];
 
int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
 
    for (cin >> N; i < N; i++) {
        cin >> arr[i].x >> arr[i].y;
        char ch;
        cin >> ch;
        if (ch == 'N')N--, i--;
    }
 
    sort(arr, arr + N, cmp);
 
    for (int i = 1; i < N; i++) {
        arr[i].p = arr[i].x - arr[0].x;
        arr[i].q = arr[i].y - arr[0].y;
    }
 
    sort(arr + 1, arr + N, cmp2);
 
    stack<int> s;
 
    int next = 2;
    s.push(0);
    s.push(1);
 
    while (next < N) {
        while (s.size() >= 2) {
            int first, second;
            second = s.top();
            s.pop();
            first = s.top();
 
            if (ccw(arr[first], arr[second], arr[next]) >= 0) {
                s.push(second);
                break;
            }
        }
        s.push(next++);
    }
 
    vector<point> v;
    while (!s.empty()) {
        int idx = s.top();
        s.pop();
        v.push_back(arr[idx]);
    }
 
    cout << v.size() << endl;
    for (int i = v.size() - 1; i >= 0; i--) {
        cout << v[i].x << " " << v[i].y << "\n";
    }
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

'algorithm' 카테고리의 다른 글

최대 합 경로 찾기(과제)  (0) 2020.04.29
의료봉사(과제)  (0) 2020.04.27

convex hull을 다루는 문제에서 

좌표를 줄 때 시작부터 cw/ccw 방향으로 좌표를 주는 경우가 있다면

랜덤하게 좌표를 주는 경우 원하는 조건에 맞게 정렬하는 방법을 정리해보자

 

* 볼록껍질의 선분을 다루기 위해서 그 선분의 점이 되는 좌표들을 미리 정렬해야함

 

반시계 방향으로 정렬한다고 가정하고

 

기준점(보통 기준점으로 x,y의 끝값에 있는 좌표를 사용, 가장 바깥쪽에 있는 좌표면 충분)을 먼저 잡고

그 기준점을 기준으로 다른 모든 점들에 대한 각도(tan)를 구함

 

1
2
3
4
5
// arr[0]은 가장 바깥쪽(현재 x,y값이 가장 작은 좌표)
for (int i = 1; i < N; i++) {
    arr[i].p = arr[i].x - arr[0].x;
    arr[i].q = arr[i].y - arr[0].y;
}
 

 

구한 각도를 기준으로 정렬(이때 반시계방향으로 좌표가 정렬됨)

 

1
2
3
4
5
bool cmp(point& a, point& b) {
    if (1LL * a.p * b.q != 1LL * a.q * b.p) return 1LL * a.q * b.p < 1LL * a.p * b.q;
    if (a.x != b.x) return a.x < b.x;
    return a.y < b.y;
}
 

 

point& a 에서 tan값은 a.q / a.p 가 되는데 위와같이 정렬하는 이유는

/ => 나눗셈을 이용하게 되면 값이 0이 되는 부분(x의 차가 없거나,y의 차가 없거나)이

분모에 올 경우 정확한 답을 찾을 수 없기 때문

tan을 위와 다르게도 정렬할 수 있다. 어쨋든 각도를 이용해서 정렬만 하면 된다

 

hull 의 내부점이 될지 선분의 기준점이 될지는 ccw으로 판단한다(당장 반시계방향의 좌표를 구하므로)

 

스택과 ccw을 이용해서 convex hull을 찾는다

 

첫번째 인자는 기준점, 두번쨰 인자는 반시계방향의 첫번째 좌표, 세번째 인자는 반시계방향의 두번째 좌표

 

3번째 인자에 대한 ccw가 >0 이 되면 왼쪽에 위치하는 점이므로 볼록껍질의 좌표가 될 수 있는 부분,

그 이외는 좌표가 될 수 없는 부분이 된다

 

ccw 가 >0 이면 두번째인자를 스택에 푸쉬(그래야 다음 확인때 첫번째로 사용가능함), 세번째 인자 역시 스택에 푸쉬

 

단, 비교해야할 선분(1,2번째인자로 만든 선분)이 필요하므로 최소한 스택의 값은 2이상 유지되야한다

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
stack<int> s;
 
int next = 2;
s.push(0);
s.push(1);
while (next < N) {
    while (s.size() >= 2) {
        int first, second;
        second = s.top();
        s.pop();
        first = s.top();
            if (ccw(arr[first], arr[second], arr[next]) > 0) {
            s.push(second);
            break;
        }
    }
    s.push(next++);
}
 

 

이렇게 마지막 좌표까지 탐색하면 현재 스택에 남아있는 좌표가 반시계방향에 대한 좌표가 된다

'algorithm > algorithm' 카테고리의 다른 글

STL 사용할때 주의할 것(set,map,...)  (0) 2020.04.10
Point in a Polygon - 다각형 내부점 판단  (0) 2020.04.07
bit masking (비트마스킹 정리)  (0) 2020.03.14
소인수분해  (0) 2020.02.28
기본 기하 공식  (0) 2020.02.28

uva : https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3145

 

espa에서는 괜찮은데 uva에서 제출해봤는데 TLE가 뜬다..

아무래도 소스가 lct나 splay를 쓰지않은 탐색코드이고 espa의 tc가 uva보다 약하기 때문인 것 같은데

lct ? splay를 공부해서 제출해봐야겠다.

 

지금 소스는 espa에서는 빠르게 통과되는 코드로

type2, 3번의 시간을 최대한 단축시키기 위해서

height 높이 개념을 이용했다.

 

LCA를 알면 좀더 빠르게 해결할 수 있다는데 뭐 통과는 되니까 일단 올려놓고

고급 자료구조를 공부한 후에 다시 적용해봐야겠다.

 

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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <set>
#include <cmath>
#include <limits>
#include <cstring>
#include <string>
using namespace std;
 
struct NODE {
    int root = -1;
    int pn = -1;
    int pn_color = -1;
    int height = -1;
    struct pii {
        int num;
        int color;
    };
    vector<pii> other;
}node[50001];
 
bool visit[50001];
bool color_arr[31];
int inn, inm;
int join = 0;
int answer_edge, answer_color;
 
int check_tree(int x) {
    answer_edge++;
    if (color_arr[node[x].pn_color] == false) {
        answer_color++;
        color_arr[node[x].pn_color] = true;
    }
 
    return node[x].pn;
}
 
void make_height2(int x, int y) {
    memset(color_arr, 0sizeof(color_arr));
    while (node[x].height != node[y].height) {
        if (node[x].height > node[y].height) x = check_tree(x);
        else y = check_tree(y);
    }
    if (x != y) {
        while (x != y) {
            x = check_tree(x);
            y = check_tree(y);
        }
    }
}
 
int color_change(int x, int c) {
    for (int i = 0; i < node[node[x].pn].other.size(); i++) {
        if (node[node[x].pn].other[i].num == x) {
            node[node[x].pn].other[i].color = c;
            break;
        }
    }
    node[x].pn_color = c;
    return node[x].pn;
}
 
void make_height(int x, int y, int c) {
    while (node[x].height != node[y].height) {
        if (node[x].height > node[y].height) x = color_change(x, c);
        else y = color_change(y, c);
    }
 
    if (x != y) {
        while (x != y) {
            x = color_change(x, c);
            y = color_change(y, c);
        }
    }
}
 
void delete_node(int x, int y) {
    for (int i = 0; i < node[x].other.size(); i++) {
        if (node[x].other[i].num == y) {
            node[x].other.erase(node[x].other.begin() + i, node[x].other.begin() + i + 1);
            break;
        }
    }
}
 
void change_father(int x, int y, int c) {
    if (node[x].root != x)    delete_node(node[x].pn, x);
 
    node[y].other.push_back({ x, c });
    node[x].pn_color = c;
 
    queue<pair<pair<int,int>,int> > q;
    q.push({ {x,y},node[y].height });
 
    while (!q.empty()) {
        int temp = q.front().first.first;
        int p = q.front().first.second;
        int h = q.front().second;
        q.pop();
 
        node[temp].root = node[y].root;
        node[temp].pn = p;
        node[temp].height = h + 1;
        for (int i = 0; i < node[temp].other.size(); i++) {
            q.push({{ node[temp].other[i].num, temp}, h+1});
        }
    }
}
 
bool check_father(int x, int y) {
    if (x == y) return true;
    if (node[x].root == x) return false;
    return check_father(node[x].pn, y);
}
 
void insert_node(int num, int parent, int color) {
    if (parent == 0) { // root
        visit[num] = true;
        node[num].height = 0;
        node[num].pn = num;
        node[num].root = num;
        join++;
        return;
    }
 
    if (node[parent].root == -1return;
    if (visit[num]) {
        join++;
        return;
    }
 
    visit[num] = true;
    node[num].root = node[parent].root;
    node[num].pn = parent;
    node[num].pn_color = color;
    node[num].height = node[parent].height + 1;
    node[parent].other.push_back({ num, color });
    join++;
}
 
int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
 
    vector<pair<pair<intint>int> > in;
    cin >> inn >> inm;
 
    for (int i = 1; i <= inn; i++) {
        int num;
        cin >> num;
        in.push_back({ {num,0},i });
    }
    for (int i = 0; i < inn; i++) {
        int col;
        cin >> col;
        in[i].first.second = col;
    }
    sort(in.begin(), in.end());
 
    while (join != inn) {
        join = 0;
        for (int i = 0; i < inn; i++)
            insert_node(in[i].second, in[i].first.first, in[i].first.second);
    }
    for (int i = 1; i <= inn; i++) visit[i] = 0;
 
    while (inm--) {
        int type, x, y, c;
        cin >> type >> x >> y;
        if (type == 1) {
            cin >> c;
            if (x == y) continue;
            if (node[x].root != node[y].root) change_father(x, y, c);
            else {
                if (!check_father(y, x)) change_father(x, y, c);
            }
        }
        if (type == 2) {
            cin >> c;
            if (x == y || node[x].root != node[y].root) continue;
            make_height(x, y, c);
        }
        if (type == 3) {
            if (x == y || node[x].root != node[y].root)
                cout << "0 0\n";
            else {
                answer_edge = answer_color = 0;
                make_height2(x, y);
                cout << answer_edge << " " << answer_color << "\n";
            }
        }
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

'algorithm > uva' 카테고리의 다른 글

uva 10205번 stack 'em up  (0) 2020.04.27
uva 384번 Slurpys, BOJ 14906번 스러피  (0) 2020.03.31
uva 10150번 Doublets  (0) 2020.03.27
uva 10469번 To Carry or not to Carry  (0) 2020.03.23
uva 10010번 Where's Waldorf?  (0) 2020.03.23

uva : https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=5&page=show_problem&problem=320

 

BOJ : https://www.acmicpc.net/problem/14906

 

문제를 보면서 그대로 구현했는데

소스가 좀 더러울 수 있지만 최대한 정리해봤습니다.

 

재귀를 이용하여 문제를 해결했습니다.

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
#include <iostream>
#include <string>
using namespace std;
 
int slumps(string str, int idx, bool si) {
    if (idx >= str.size()) return -1;
    if (si) {
        if (!(str[idx] == 'D' || str[idx] == 'E')) return -1;
        if (idx + 1 < str.size() && str[idx + 1== 'F'return slumps(str, idx + 2false);
    }
    else {
        if (str[idx] == 'F'return slumps(str, idx + 1false);
        if (str[idx] == 'G' && str[idx - 1== 'F'return idx;
        if (str[idx] == 'D' || str[idx] == 'E'return slumps(str, idx, true);
    }
    return -1;
}
 
int slimps(string str, int idx, bool si) {
    if (idx >= str.size()) return -1;
    if (si) {
        if (str[idx] != 'A'return -1;
        if (idx + 1 < str.size()) {
            if (str[idx + 1== 'H'return idx + 1;
            else return slimps(str, idx + 1false);
        }
    }
    else {
        if (str[idx] == 'B') {
            int res = slimps(str, idx + 1true);
            if (res != -1 && str[res + 1== 'C'return res + 1;
        }
        if (str[idx] == 'D' || str[idx] == 'E') {
            int res = slumps(str, idx, true);
            if (res != -1 && str[res + 1== 'C'return res + 1;
        }
    }
    return -1;
}
 
bool solve(string str) {
    int idx = slimps(str, 0true);
    if (idx == -1return false;
    idx = slumps(str, idx + 1true);
    return idx == str.size() - 1 ? true : false;
}
 
int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
 
    cout << "SLURPYS OUTPUT\n";
    int tc;
    cin >> tc;
    while (tc--) {
        string str;
        cin >> str;
        if (solve(str)) cout << "YES\n";
        else cout << "NO\n";
    }
    cout << "END OF OUTPUT";
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

'algorithm > uva' 카테고리의 다른 글

uva 10205번 stack 'em up  (0) 2020.04.27
uva 11994번 Happy Painting!  (0) 2020.04.06
uva 10150번 Doublets  (0) 2020.03.27
uva 10469번 To Carry or not to Carry  (0) 2020.03.23
uva 10010번 Where's Waldorf?  (0) 2020.03.23

+ Recent posts