예전에 풀었던 문제였지만 너무 괴랄한 코드를 작성했었기에 다시 풀어보았다.
아래는 예전에 제출했던 괴랄한 코드이다. 해석조차 힘들다.
#include <stdio.h>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
typedef pair<pair<int, int>, int> pp;
typedef pair<int, int> p;
set<p>s;
set < pair<p, p>> chkset;
int dir[4][2] = { {0,1},{-1,0},{0,-1},{1,0} };
int rdir[9][2] = { {0,0}, {-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0} };
int ans = 0;
p move(p a, int k) {
return { a.first + dir[k][0],a.second + dir[k][1] };
}
int change(int k) {
k = k + 1;
if (k == 4) k = 0;
return k;
}
void chk(p cur) {
bool res[9] = { false };
for (int i = 1; i <= 8; i++) {
if (s.find({ cur.first + rdir[i][0],cur.second + rdir[i][1] }) != s.end()) {
res[i] = true;
}
}
if (res[1] && res[2] && res[8]) {
if (chkset.find({ {cur.first + rdir[1][0],cur.first + rdir[2][0]},{cur.second + rdir[1][1],cur.second + rdir[8][1] } }) == chkset.end()) {
chkset.insert({ {cur.first + rdir[1][0],cur.first + rdir[2][0]},{cur.second + rdir[1][1],cur.second + rdir[8][1] } });
ans += 1;
}
}
if (res[2] && res[3] && res[4]) {
if (chkset.find({ {cur.first + rdir[2][0],cur.first + rdir[3][0]},{cur.second + rdir[3][1],cur.second + rdir[4][1] } }) == chkset.end()) {
chkset.insert({ {cur.first + rdir[2][0],cur.first + rdir[3][0]},{cur.second + rdir[3][1],cur.second + rdir[4][1] } });
ans += 1;
}
}
if (res[4] && res[5] && res[6]) {
if (chkset.find({ {cur.first + rdir[6][0],cur.first + rdir[5][0]},{cur.second + rdir[4][1],cur.second + rdir[5][1] } }) == chkset.end()) {
chkset.insert({ {cur.first + rdir[6][0],cur.first + rdir[5][0]},{cur.second + rdir[4][1],cur.second + rdir[5][1] } });
ans += 1;
}
}
if (res[6] && res[7] && res[8]) {
if (chkset.find({ {cur.first + rdir[8][0],cur.first + rdir[6][0]},{cur.second + rdir[8][1],cur.second + rdir[6][1] } }) == chkset.end()) {
chkset.insert({ {cur.first + rdir[8][0],cur.first + rdir[6][0]},{cur.second + rdir[8][1],cur.second + rdir[6][1] } });
ans += 1;
}
}
}
int main() {
int n, x, y, d, g;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
vector<pp>v;
scanf("%d %d %d %d", &x, &y, &d, &g);
s.insert({ y,x });
v.push_back({ move({ y,x }, d),d });
s.insert(move({ y,x }, d));
for (int j = 0; j < g; j++) {
for (int p = v.size() - 1; p >= 0; p--) {
pp next = { move(v[v.size() - 1].first, change(v[p].second)),change(v[p].second) };
v.push_back({ next.first , next.second });
s.insert({ next.first });
}
}
}
for (auto it = s.begin(); it != s.end(); it++) {
chk(*it);
}
printf("%d", ans);
return 0;
}
이번에 풀떄는 한 세대가 증가할 때의 규칙을 이용하여 풀었다.
드레곤 커브의 좌표가 아닌 방향을 저장해간다고 했을 때,
1세대가 0,1
이었을경우 2세대는 0,1,2,1
이 된다.
즉, 이전까지의 세대의 진행방향을 저장한 배열을 거꾸로 읽으며 1씩 더해 저장해주면 시계방향으로 90도 회전하고 커브의 끝에 붙여주는 과정을 나타낸다.
위의 규칙을 찾은 후 다음과 같은 과정으로 해결했다.
좌표의 범위가 100 * 100 이므로 SET에 저장되는 좌표는 최대 10000개 이고 정사각형임으로 보려면 x+1,y
, x,y+1
, x+1,y+1
이 3개의 점이 SET에 존재하는지 확인해주면 되므로 O(nlogn)
시간에 해결할 수 있다.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int dir[4][2] = { {1,0} ,{0,-1},{-1,0},{0,1} };
typedef pair<int, int> p;
set<p>s;
void draw(int x, int y, int d, int g) {
s.insert({ x,y });
vector<int>v;
v.push_back(d);
while (g--) {
for (int i = v.size() - 1; i >= 0; i--)
v.push_back((v[i] + 1) % 4);
}
for (auto it : v) {
x += dir[it][0]; y += dir[it][1];
s.insert({ x,y });
}
return;
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n; cin >> n;
for (int i = 0; i < n; i++) {
int x, y, d, g; cin >> x >> y >> d >> g;
draw(x, y, d, g);
}
int ans = 0;
for (auto it : s) {
if (s.find({ it.first,it.second + 1 }) == s.end()) continue;
if (s.find({ it.first + 1,it.second }) == s.end()) continue;
if (s.find({ it.first + 1,it.second + 1 }) == s.end()) continue;
ans += 1;
}
cout << ans;
return 0;
}