문제 설명
드래곤 커브는 다음과 같은 세 가지 속성으로 이루어져 있으며, 이차원 좌표 평면 위에서 정의된다. 좌표 평면의 x축은 → 방향, y축은 ↓ 방향이다.
- 시작 점
- 시작 방향
- 세대
0세대 드래곤 커브는 아래 그림과 같은 길이가 1인 선분이다. 아래 그림은 (0, 0)에서 시작하고, 시작 방향은 오른쪽인 0세대 드래곤 커브이다.
1세대 드래곤 커브는 0세대 드래곤 커브를 끝 점을 기준으로 시계 방향으로 90도 회전시킨 다음 0세대 드래곤 커브의 끝 점에 붙인 것이다. 끝 점이란 시작 점에서 선분을 타고 이동했을 때, 가장 먼 거리에 있는 점을 의미한다.
2세대 드래곤 커브도 1세대를 만든 방법을 이용해서 만들 수 있다. (파란색 선분은 새로 추가된 선분을 나타낸다)
3세대 드래곤 커브도 2세대 드래곤 커브를 이용해 만들 수 있다. 아래 그림은 3세대 드래곤 커브이다.
즉, K(K > 1)세대 드래곤 커브는 K-1세대 드래곤 커브를 끝 점을 기준으로 90도 시계 방향 회전 시킨 다음, 그것을 끝 점에 붙인 것이다.
크기가 100×100인 격자 위에 드래곤 커브가 N개 있다. 이때, 크기가 1×1인 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인 정사각형의 개수를 구하는 프로그램을 작성하시오. 격자의 좌표는 (x, y)로 나타내며, 0 ≤ x ≤ 100, 0 ≤ y ≤ 100만 유효한 좌표이다.
입력
첫째 줄에 드래곤 커브의 개수 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좌표가 증가하는 방향 (↓)
출력
첫째 줄에 크기가 1×1인 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인 것의 개수를 출력한다.
생각
드래곤커브를 구하는 함수와 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인지 확인하는 함수 두 개가 필요하다.
먼저 드래곤커브를 어떻게 구하는지에 대해 살펴보자. 아직 다른 고수분들의 코드를 보지는 않았지만 문제를 쳐다보고 있으니 90도 회전에 대한 어떤 규칙이 떠올랐다.
0 방향에서 90도 회전을 하면 1 방향이 된다. 1방향에서 90도 회전을 하면 2 방향이 된다. 2 방향에서 90도 회전하면 3 방향이 되고, 3방향에서 90도 회전을 하면 다시 0 방향이 된다. (끝점을 기준으로 회전 시)
이런 규칙을 바탕으로 3 3 0 3에 대한 드래건 커브를 구해보자.
나는 배열에 타입을 먼저 넣고 타입에 맞게 회전하는 방식을 선택했다.
처음엔 0 방향이므로 배열에 0을 넣어주자. -> ( 0 )
0 방향으로 갔으므로 1 방향을 넣어주자. (끝점을 기준으로 하므로 접근을 맨 뒤에서부터 한다) -> ( 0 1 )
뒤에서부터 접근하므로 이전의 방향 2개에 대해서 90도 회전한 타입을 넣어준다. 즉, 2 방향과 1방향을 넣어준다. -> ( 0 / 1 / 2 1 )
마지막 3세대에선 다음과 같이 될 것이다. (0 / 1 / 2 1 / 2 3 2 1 )
이제 타입이 정해졌으니 시작점을 잡고 각 타입별로 좌표를 더해주기만 하면 드래곤커브가 완성된다.
이제 정사각형의 각 꼭지점이 드래곤 커브에 일부인지를 확인하면 된다.
bfs방식과 비슷하게 접근했는데 드래곤커브의드래건 커브의 일부라면 그 점에서 크기가 1x1인 정사각형이 되게 좌표를 더하면서 모두 드래건 커브의 일부이면 square count를 증가시켜줬다. 물론 여기서 범위를 벗어나는 경우 등을 고려해줘야 한다.
세부적인 설명은 주석에 적도록 하겠다.
코드
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
|
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
//x가 가로 y가 세로
static int[][] map = new int[101][101];
static int square_count = 0;
//인덱스 별로 0,1,2,3 방향이다.
static int[] dx = {1,0,-1,0};
static int[] dy = {0,-1,0,1};
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
for(int t=0; t<n; t++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int type = Integer.parseInt(st.nextToken());
int gen = Integer.parseInt(st.nextToken());
dragonCurve(x,y,type,gen);
}
checkSquare();
System.out.println(square_count);
}
/*
* type
* 0: x좌표 증가 (우)
* 1: y좌표 감소 (상)
* 2: x좌표 감소 (좌)
* 3: y좌표 증가 (하)
*/
public static void dragonCurve(int x,int y, int type, int gen) {
//각 방향을 담을 수 있는 ArrayList이다.
ArrayList<Integer> arr = new ArrayList<Integer>();
int tmp_type = type;
arr.add(tmp_type);
for(int i=1; i<=gen; i++) {
//맨 뒤에서부터 접근한다. 아예 스택으로 해도 될 것 같다.
for(int j=arr.size()-1; j>=0; j--) {
//나누기 연산자를 통해 0,1,2,3의 값만 나올 수 있게 한다.
tmp_type = (arr.get(j) + 1)%4;
arr.add(tmp_type);
}
}
int tmp_x = x;
int tmp_y = y;
for(int i=0; i<arr.size(); i++) {
map[tmp_y][tmp_x] = 1;
tmp_x += dx[arr.get(i)];
tmp_y += dy[arr.get(i)];
}
//마지막에 넣어주지 않으므로 넣어주는 처리한다.
map[tmp_y][tmp_x] = 1;
}
public static void checkSquare() {
int[] dx = {1,0,1};
int[] dy = {0,1,1};
int check_count = 0;
for(int i=0; i<map.length; i++) {
for(int j=0; j<map[0].length; j++) {
if(map[i][j] == 1) {
for(int k=0; k<3; k++) {
int tmp_i = i + dy[k];
int tmp_j = j + dx[k];
//범위를 넘어가지 않고 드래곤 커브의 일부이면 check_count를 증가시킨다.
if(tmp_i>=0 && tmp_i<101 && tmp_j>=0 && tmp_j<101 && map[tmp_i][tmp_j] == 1) {
check_count++;
}
}
//check_count가 3이 되면 4개의 꼭지점이 모두 드래곤 커브의 일부임이 확인된다.
if(check_count == 3) {
square_count++;
}
check_count = 0;
}
}
}
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
'알고리즘 > 코딩 - 백준' 카테고리의 다른 글
[Java][자바][백준][2309번] 일곱 난쟁이 - 브루트포스 이용 (0) | 2019.08.29 |
---|---|
[Java][자바][백준][5545번] 최고의 피자 (0) | 2019.08.28 |
[Java][자바][백준][4963번] 섬 개수 (0) | 2019.08.26 |
[Java][자바][백준][6593번] 상범 빌딩 (0) | 2019.08.25 |
[Java][자바][백준][7562번] 나이트의 이동 (1) | 2019.08.24 |