[BOJ/백준 15685/C++] 드래곤 커브
https://www.acmicpc.net/problem/15685
15685번: 드래곤 커브
첫째 줄에 드래곤 커브의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 드래곤 커브의 정보가 주어진다. 드래곤 커브의 정보는 네 정수 x, y, d, g로 이루어져 있다. x와 y는 드래곤 커
www.acmicpc.net
[문제 요약]
- 드래곤 커브는 세 가지 속성으로 이루어져 있다. ( 시작 점, 시작 방향 , 세대 )
- x축은 → 방향 y축은 ↓ 방향이다.
- 0세대 드래곤 커브는 아래 그림과 같이 길이가 1인 선분이면서 (0,0)에서 시작하고 시작 방향은 →(오른쪽)이다.
- 1세대 드래곤 커브는 0세대 드래곤 커브를 끝 점을 기준으로 시계 방향으로 90도 회전시킨 다음 0세대 드래곤 커브의 끝점에 붙인 것이다. 끝 점은 시작 점에서 선분을 타고 이동했을 때, 가장 먼 거리에 있는 점을 의미한다.
- 2세대 드래곤 커브
- 3세대 드래곤 커브
- 즉 K세대 (K>1) 드래곤 커브는 K-1세대 드래곤 커브를 끝 점을 기준으로 90도 시계 방향 회전시킨 다음, 그것을 끝 점에 붙인 것이다. 크기 100x100 격자 위에 드래곤 커브가 N개 있다. 크기가 1x1인 정사각형의 네 꼭짓점이 모두 드래곤커브의 일부인 정사각형의 개수를 구하여라
[문제 조건]
- 첫째 줄에 드래곤 커브의 개수 N(1 ≤ N ≤ 20 )가 주어진다.
- 둘째 줄부터 N개의 줄에는 드래곤 커브의 정보가 주언진다. 드래곤 커브의 정보는 네 정수 x,y,d,g,로 이루어져 있다. x와 y는 드래곤 커브의 시작 점, d는 시작 방향, g는 세대이다. ( 0 ≤ x,y ≤ 100 , 0 ≤ d ≤ 3 , 0 ≤ g ≤ 10)
- 드래곤 커브는 격자 밖으로 나가지 않으며, 서로 겹칠 수 있다.
- 방향은 0, 1, 2, 3 중 하나이고, 다음을 의미 한다.
- 0 : x 좌표가 증가하는 방향 (→)
- 1: y좌표가 감소하는 방향 (↑)
- 2: x좌표가 감소하는 방향 (←)
- 3: y좌표가 증가하는 방향 (↓)
[문제 풀이]
(mp는 격자판의 꼭짓점 사용여부를 나타내는 2차원 배열)
먼저 격자판은 2차원배열의 형태로 생각했다. mp의 값은 좌표가 드래곤 커브에 사용되는 꼭짓점인지 아닌지 사용여부를 나타내는 bool형의 2차원 배열이다.
그 다음 과정은 예제를 통해 설명하겠다.
문제의 첫 번째 예제의 두 번째 경우(4, 2, 1, 3)을 예를들어 점을 찍는 방법을 서술하겠다.
1세대까지 진행시켰을 때 시작점 부터 좌표를 적어보면 (2,4) → (1,4) → (1,3) 이고 방향은 1 → 2이다.
여기서 2세대까지 진행시키면
이와 같은 그림이 되고 좌표는 (2,4) → (1,4) → (1,3) → (2,3) → (2,2)이고 방향은 1 → 2 → 3 → 2 가 된다
여기서 본인이 찾은 규칙을 설명하자면
K-1세대까지 방향을 저장해 놓은 배열의 마지막 값부터 처음 까지 위 그림을 기준으로 시계방향으로 한칸 이동 후 반대편의 값이 다음 방향이 된다.
무슨 뜻이냐 1세대 까지 진행시켰을 때 방향을 보면 1→2로 저장해놨을 것이다. 여기서 2부터 확인해 보면, 위 그림을 기준으로 2의 시계방향은 1이다. 그 다음 반대편 값은 3이다. 그리고 1 → 2 → 3 와 같이 배열에 추가해준다. 나머지 1도 똑같이 하면 1→2→3→2가 저장되어 있을 것이다.
그리고 이 배열을 좌표 배열에 대응시켜 생각해보면
(2,4) → (1,4) → (1,3)
1 → 2 → 3 → 2
와 같은 상태일텐데 여기서 각 좌표는 대응되는 방향을 저장해둔 배열의 값 방향으로 이동시키면 다음 좌표가 된다.
그림과 같이 다음 좌표들을 좌표배열 뒤에 계속 추가해주면 된다.
이런 방식으로 격자판에 true값으로 바꿔주면 드래곤 커브를 모두 표시할 수 있다.
그 다음 네 꼭짓점 모두 드래곤커브의 일부가 되는 정사각형을 찾는 방법은 아주 간단하다
모든 격자판을 확인하면서 현재 좌표가 (y,x)일때 (y,x) , (y,x+1) , (y+1,x) , (y+1,x+1)이 모두 true값이면 네 꼭짓점 모두 드래곤커브이 일부가 되는 정사각형이란 뜻이다.
[소스 코드]
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
#include <deque>
#include <math.h>
#include <map>
#include <queue>
#include <stack>
using namespace std;
int N;
vector<vector<bool>> mp;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,-1,0,1 };
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
mp.resize(101);
for (int i = 0; i <= 100; i++) mp[i].resize(101);
cin >> N;
while (N--)
{
int x, y, d, g;
cin >> x >> y >> d >> g;
vector<pair<int, int>> dt;
vector<int> direct;
direct.push_back(d);
dt.push_back({ y,x });
dt.push_back({ y + dy[d], x + dx[d] });
mp[y][x] = 1;
mp[y + dy[d]][x + dx[d]] = 1;
int direct_pos = 1;
int direct_cnt = 1;
for (int i = 0; i < g; i++)
{
for (int j = direct.size() - 1; j >= 0; j--)
{
int tmp = direct[j];
if (tmp == 0) tmp = 3;
else tmp--;
tmp = (tmp + 2) % 4;
direct.push_back(tmp);
}
for (int j = direct_pos; j < direct.size(); j++)
{
dt.push_back({ dt[j].first + dy[direct[j]], dt[j].second + dx[direct[j]] });
mp[dt[j].first + dy[direct[j]]][dt[j].second + dx[direct[j]]] = 1;
direct_pos = j;
}
direct_pos++;
}
}
int ans = 0;
for (int i = 0; i <= 99; i++)
{
for (int j = 0; j <= 99; j++)
{
if (mp[i][j] == 1 && mp[i + 1][j] == 1 && mp[i][j + 1] == 1 && mp[i + 1][j + 1] == 1)
ans++;
}
}
cout << ans;
}

굳