백준 1074 - Z

Updated:

C++

1074 번 - Z

문제

2차원 배열을 Z모양으로 탐색하려고 한다.
만약, N > 1이 라서 왼쪽 위에 있는 칸이 하나가 아니라면, 배열을 크기가 2N-1 × 2N-1로 4등분 한 후에 재귀적으로 순서대로 방문한다.
N이 주어졌을 때, r행 c열을 몇 번째로 방문하는지 출력하는 프로그램을 작성하시오.
문제 출처

접근 방법

겉보기에 재귀를 써야할 것 같지만, 조건문 만을 이용하여 풀 수 있었다.
2N의 크기인 보드를 지속하여 4등분을 하며 주어진 위치의 좌표가 4등분 된 보드 중 어느 위치에 있는지 확인한다.

또한 4등 분을 할 때마다, 각 [1, 2, 3, 4] 보드의 시작점이 달라지며, 이 시작 점의 수를 게속하여 합하는 방법으로 몇번째에 방문하는 지 알 수 있다.
따라서 만약 n = 1이면 각 등분된 시작점은 [0, 1, 2, 3]이며,
n = 2이면 [0, 4, 8, 12]
n = 3이면 [0, 16, 32, 48]
… 즉 4N에 따라 시작점이 달라진다.

만약 주어진 예시와 같이 N이 3이고 r과 c가 7,7이면,

4등분을 3번하며, 처음 4등분 하였을시 가장 왼쪽 아래에 위치한다.
따라서 48을 더해주며, 그 다음 등분 시에도 4번의 위치, 가장 왼쪽 아래이므로 12를 더해주고, 마지막에도 동일하므로 3을 더해준다.
즉 48 + 12 + 3에 따라 정답인 63이 나온다.

구현

N의 크기만큼 반복을 해주며, 각 보드를 1/4를 하여 위치를 찾는다.
위치를 찾으면 그 좌표를 왼쪽 위로 정렬한다고 생각하고 이동시켜 준다.
즉 n = 3일때 (5,3) 점을 찾고 싶으면, 3번 위치 이므로 보드가 n=2의 크기가 되었을 시 y축 값이 (5-4, 3)이 되어 (1,3)으로 재정렬 되고 n=2의 기준으로 새로히 보드를 4등분하여 좌표가 현재 나누어진 보드의 어느 위치에 있는지 확인한다.

코드

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;

int n, r, c;
int result;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> r >> c;

	for (int idx = n - 1; idx >= 0; idx--) {
		int curBound = pow(2, idx);		// 4등분을 나눌 기준 선. 기준선은 2<sup>N</sup>에 따라 증가한다.
		int pst;
		if (r < curBound && c < curBound) 		// 1번 위치
			pst = 0;
		else if (r < curBound && c >= curBound) {	// 2번 위치
			pst = 1;
			c -= curBound;
		}
		else if (r >= curBound && c < curBound) {	// 3번 위치
			pst = 2;
			r -= curBound;
		}
		else {										// 4번 위치
			pst = 3;
			r -= curBound;
			c -= curBound;
		}

		result += pow(4, idx) * pst;				// 4등분 된 보드에서 현재 좌표가 위치한 자리의 시작 값을 더해준다.
	}

	cout << result;
	return 0;
}

후기 및 개선할 점

재귀적으로 생각해보려다 쉽게 떠오르지 않아, 일단 조건문으로 풀어 해결하였다.