https://www.acmicpc.net/problem/29721
문제 난이도는 쉬운 편이지만 cpp의 unordered_set에 대해 새롭게 알게된 부분이 있어서 정리해봅니다.
문제는 체스판 위에 놓여져 있는 다바바를 이동시킬 수 있는 칸이 몇 개인지 세기만 하면 됩니다.
다바바는 상하좌우로 2칸만 이동할 수 있으며 나이트처럼 경로에 위치한 다른 기물을 뛰어 넘을 수 있습니다.
체스판의 크기가 10만이므로 배열로는 해결할 수 없습니다.
set과 unordered_set 둘다 사용이 가능했지만 정렬이 필요없기에 unordered_set을 사용했습니다.
문제 로직은 간단합니다.
다바바는 맵 밖이나 다른 다바바가 위치한 좌표에는 갈 수 없으니 최초 다바바의 위치는 set에 미리 넣어둡니다.
이후에 상하좌우로 2칸씩 이동시켜서 set에 insert하고, 그 횟수를 구하면 됩니다.
확실히 메모리와 시간이 줄어드는 것을 확인할 수 있습니다.
저는 처음에는 set을 활용하여 문제를 풀었고, 시간을 줄이기 위해 unordered_set으로 바꾸는 도중에 컴파일 에러가 떴는데
unordered_set은 key를 해시화해서 사용하는데 pair에 대한 기본 해시 함수가 없기 때문에 발생한 에러였고, 해시 함수를 직접 정의를 해야했습니다.
1
2
3
4
5
|
struct pair_hash {
size_t operator()(const pii& p) const {
return hash<int>()(p.first) ^ hash<int>()(p.second);
}
};
|
cs |
이런식으로 해시 함수를 직접 정의할 수 있습니다.
다만 이렇게 둔다면 p.first와 p.second가 비슷한 값이면 해시 충돌이 많이 발생한다고 합니다.
특히 이 문제에서는 상하좌우로 2칸씩만 이동하기 때문에 치명적인 문제가 될 수 있겠다는 생각이 들었습니다.
역시나 TLE가 떴습니다.
p.first나 p.second 둘 중 하나에 소수를 곱해준다면 충돌 확률을 낮추는 효과를 가져올 수 있습니다.
다만 너무 큰 숫자를 곱하게 되면 곱셈 연산에 소요되는 시간이 더 많이 발생할 수 있으니 적당한 수를 곱하는게 좋아보입니다.
그리고 양쪽 모두 소수를 곱하는 방법도 있는데 충돌은 줄어들겠지만 그만큼 곱셈 연산이 더 늘어나서 시간이 더 소요될 수 있습니다.
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
|
#include <iostream>
#include <vector>
#include <unordered_set>
#define MAX 100001
using namespace std;
typedef pair<int, int> pii;
struct pair_hash {
size_t operator()(const pii& p) const {
return hash<int>()(p.first) ^ (hash<int>()(p.second) * 31);
}
};
unordered_set<pii, pair_hash> s;
vector<pii> v;
int direct[4][2] = { {2,0},{0,2},{-2,0},{0,-2} };
int N, K;
void func() {
int ret = 0;
for (auto xy : v) {
int x = xy.first;
int y = xy.second;
for (int d = 0; d < 4; d++) {
int nx = x + direct[d][0];
int ny = y + direct[d][1];
if (nx <= 0 || ny <= 0 || nx > N || ny > N) continue;
if (s.find({ nx,ny }) != s.end()) continue;
ret++;
s.insert({ nx,ny });
}
}
cout << ret << '\n';
}
void input() {
int x, y;
cin >> N >> K;
for (int i = 0; i < K; i++) {
cin >> x >> y;
v.push_back({ x,y });
s.insert({ x,y });
}
}
int main() {
cin.tie(NULL); cout.tie(NULL);
ios::sync_with_stdio(false);
input();
func();
return 0;
}
|
cs |
'algorithm > data-structure' 카테고리의 다른 글
boj 15926 현욱은 괄호왕이야!! (1) | 2023.07.24 |
---|---|
boj 21939 문제 추천 시스템 Version 1 (0) | 2022.02.11 |
boj 17299 오등큰수 (0) | 2021.02.22 |
boj 9372 상근이의 여행 (0) | 2021.02.09 |
boj 1158 요세푸스 문제 (0) | 2021.02.09 |