본문으로 바로가기

[분할 정복] Z 1074 ○

category ps/분할 정복 2021. 10. 16. 23:18

문제 해설 및 주의사항

1. 종이의 개수 문제 와 유사하다.


 

풀이

1. N 이 최대 15이다.

 

2. 문제를 분할하자

 

a. 현재 정사각형을 4등분한다.

b. 2x2 정사각형이 되면, z 모양으로 순회한다.

c. r, c 에 방문하면 순회를 마친다.

 

3. flag 전역변수

- r, c 를 만나면 flag 를 false 로 바꾸어서 이후의 재귀함수가 작동하지 않게 한다.

 

4. 재귀 함수의 시간을 줄이는 조건 추가하기

- r, c 가 현재 정사각형에 들어있지 않다면, ret 에 정사각형의 크기만큼을 더해주고 끝낸다.


풀이코드 (시간 초과)

#include <iostream>

using namespace std;
const int MAX = 100000;

int n, r, c;

/*

a. 현재 정사각형을 4등분한다.

b. 2x2 정사각형이 되면, z 모양으로 순회한다.

c. r, c 에 방문하면 순회를 마친다.

*/

bool flag = true;
int solve(int y, int x, int width){
	// c.
	if(y == r && x == c) {
		flag = false;
		return 0;
	}
	if(width == 1) {
		return 1;
	}
	
	int ret = 0;

	if(flag)
		ret += solve(y, x, width / 2);
	if(flag)
		ret += solve(y, x+width/2, width/2);
	if(flag)
		ret += solve(y+width/2, x, width/2);
	if(flag)
		ret += solve(y+width/2, x+width/2, width/2);
	
	return ret;
}

int main(){
	cin >> n >> r >> c;
	
	cout << solve(0,0,1 << n) << endl;
}

풀이코드 (정답)

#include <iostream>

using namespace std;
const int MAX = 100000;

int n, r, c;

/*

a. 현재 정사각형을 4등분한다.

b. 2x2 정사각형이 되면, z 모양으로 순회한다.

c. r, c 에 방문하면 순회를 마친다.

*/

bool flag = true;
int solve(int y, int x, int width){
	// c.
	if(y == r && x == c) {
		flag = false;
		return 0;
	}
	if(width == 1) {
		return 1;
	}
	
	int ret = 0;

	if( r < y + width && r >= y && c < x + width && c >= x){
		if(flag)
			ret += solve(y, x, width / 2);
		if(flag)
			ret += solve(y, x+width/2, width/2);
		if(flag)
			ret += solve(y+width/2, x, width/2);
		if(flag)
			ret += solve(y+width/2, x+width/2, width/2);
	}
	else{
		ret += width * width;
	}
	
	return ret;
}

int main(){
	cin >> n >> r >> c;
	
	cout << solve(0,0,1 << n) << endl;
}

 


퇴고

1. 시간 초과

- 시간을 줄이는 조건 을 어떻게 생각해낼 수 있을것인가

반응형

'ps > 분할 정복' 카테고리의 다른 글

[분할 정복] 사분면 1891  (0) 2021.10.21
[분할 정복] 트리의 순회 2263 ○  (0) 2021.10.16
하노이탑 이동 순서 (boj.kr/11729)  (0) 2021.10.14
종이의 개수 (boj.kr/1780)  (0) 2021.10.14