본문 바로가기
알고리즘/백준 & swacademy

BOJ 1074 - Z

by sun__ 2019. 7. 4.

https://www.acmicpc.net/problem/1074

재귀로 완전탐색하는 기본문제를 찾다가 접한 문제다.

 

주어진 입력을 4분할해서 좌상단 우상단 좌하단 우하단 순으로 방문하고 기저를 잘 처리해주면 되겠다 해서 처음으로 짠 코드. cnt[][] 2차원 배열로 방문 순서를 저장할까 했지만, 그냥 cnt=0부터 한개씩 올려주면서 처리하는 것으로 했다.

#include <cstdio>

int n, r, c;
int cnt, rst;
void go(int cy, int cx, int n) {
	if (n == 0) {
		if (cy == r && cx == c) rst = cnt;
		cnt++;
		return;
	}
	go(cy, cx, n - 1);
	go(cy, cx + (1 << (n - 1)), n - 1);
	go(cy + (1 << (n - 1)), cx, n - 1);
	go(cy + (1 << (n - 1)), cx + (1 << (n - 1)), n - 1);
}

int main() {
	scanf("%d %d %d", &n, &r, &c);
	go(0, 0, n);
	printf("%d\n", rst);
}

결과는 시간초과. 한 변의 최대 길이는 2^15이이므로 방문하는 칸이 2^30이 돼서 시간초과가 난 것 같다.

 

문제 풀 때 시간복잡도를 완전 잘못 생각해서 기저에서 4번의 비교를 하므로 의미는 없지만 재귀의 깊이를 한 칸 줄여봤는데 정답이 떳다. ???아직도 이게 정답인 이유를 모르겠다. 

#include <cstdio>

int n, r, c;
unsigned long long cnt, rst;
void go(int cy, int cx, int n) {
	if (n == 1) {
		
		if (cy == r && cx == c) {
			rst = cnt;
		}
		cnt++;
		if (cy == r && cx+1 == c) {
			rst = cnt;
		}
		cnt++;
		if (cy+1 == r && cx == c) {
			rst = cnt;
		}
		cnt++;
		if (cy+1 == r && cx+1 == c) {
			rst = cnt;
		}
		cnt++;
		return;
	}
	go(cy, cx, n - 1);
	go(cy, cx + (1 << (n - 1)), n - 1);
	go(cy + (1 << (n - 1)), cx, n - 1);
	go(cy + (1 << (n - 1)), cx + (1 << (n - 1)), n - 1);
}

int main() {
	scanf("%d %d %d", &n, &r, &c);
	go(0, 0, n);
	printf("%llu\n", rst);
}

 

 

좀 최적화를 할 수 있는 방법을 생각하다가, 어차피 cnt[][]배열을 채울 것이 아니라면 r,c가 포함되지 않은 블럭은 단순 연산으로 알아낼 수 있으므로 칸의 크기에 맞게 cnt를 조정해줬다.

#include <cstdio>
int n, r, c;
int cnt, rst;
void go(int cy, int cx, int n) {
	//{r,c}가 포함되지 않은 블럭이면 cnt조정후 return해버리기
	if ((r<cy || r>=cy+(1<<n)) || (c<cx || c>=cx+(1<<n))) {
		cnt += (1<<n*2);
		return;
	}
	if (cy == r && cx == c) {
    	rst = cnt;
		return;
	}
	
	go(cy, cx, n - 1);
	go(cy, cx + (1<<n-1), n - 1);
	go(cy + (1 << n - 1), cx, n - 1);
	go(cy + (1 << n - 1), cx + (1 << n - 1), n - 1);
}

int main() {
	scanf("%d %d %d", &n, &r, &c);
	go(0, 0, n);
	printf("%d\n", rst);
}

재귀가 들어가는 부분을 1/4로 단축했으니까 최악의 경우 O(loglong(2^30))쯤 될 것 같다.

 

.후기

딱 이정도 난이도가 내게 적당한 것 같다

 

 

'알고리즘 > 백준 & swacademy' 카테고리의 다른 글

BOJ 1182 - 부분수열의 합  (0) 2019.07.06
BOJ 9663 - N QUEEN  (0) 2019.07.06
BOJ 15649 - N과 M (1~12)  (0) 2019.07.06
BOJ 2448 - 별찍기11  (0) 2019.07.04
(인강)기초-dp1  (0) 2019.06.23