본문 바로가기
알고리즘&자료구조/재귀

백준 1074

by dongR 2024. 2. 26.

문제 분석

 

N=1 일때 가정

2*2 크기의 배열이 만들어지고 한 변의 길이의 반은 1(2의 n승 -1)

 

1번 사각형 : 1번 사각형이 위치한 x좌표(행)과 y좌표(열)  둘 다 half(배열의 한 변의 길이의 반)보다 작은 경우

 

2번 사각형 : 2번 사각형이 위치한 x좌표(행)이 half보다 작고 y좌표(열)은 half와 같거나 큰 경우

 

3번 사각형 : 3번 사각형이 위치한 x좌표(행)이 half와 같거나 크고 y좌표(열)은 작은 경우

 

4번 사각형 : 4번 사각형이 위치한 x좌표(행)과 y좌표(열) 둘 다 half와 같거나 큰 경우

 

 

3번 사각형을 구하기 위한 절차를 예시로 들면, 

int func(int n, int x, int y) {
    if (n == 0) return 0;
    int half = 2 * n - 1;

    // 1번 사각형
    if (x < half && y < half) {
        return func(n - 1, x, y);
    }

    // 2번 사각형
    if (x < half && y >= half) {
        return half * half + func(n - 1, x, y - half);
    }

    // 3번 사각형
    if (x >= half && y < half) {
        return 2 * half * half + func(n - 1, x - half, y);
    }

    // 4번 사각형
    if (x >= half && y >= half) {
        return 2 * half * half + func(n - 1, x - half, y - half);
    }
}

func(1, 0, 1);

3번 사각형이 위치한 조건에 따라서 재귀함수를 호출하고 n=0 경우에 0을 반환해서 마지막으로 재귀함수 호출이 종료되도록 하였다. 

1~4번 사각형 모두 0을 더하도록 하는 조건을 수행한다. 

 

 

n=2 일때도, n=1 일때의 가정을 성립하는지 확인해보자

2번 사각형 (0,2) 위치의 값을 구하는 절차를 확인하면

 

첫번째 재귀함수 호출시 n=2일때 이므로 half는 2가 된다.

func(2, 0, 2);
return 2 * half * half + func(1, 0, 2 - half)

 

n=1 이므로 재귀함수가 종료되지 않고 1번 사각형에서 (0,0) 위치에 있는 값을 구한다.

n=1 일때, half값은 1이 되니까 1번 사각형 안에서 다시 1,2,3,4 번의 사각형으로 구분된다.

func(1, 0, 0);
return func(0, 0, 0)

 

n=0 이므로 재귀함수는 종료되고 역순으로 스택 프레임에서 함수를 하나씩 제거(종료)시킨다.

func(0,0,0)
if(n==0) return 0;

 

n=k 일때 성립하고 n=k+1 때도 성립하므로 k+2, k+3 ... 성립한다는 것을 알 수 있다.

 

 

코드

#include<iostream>	
using namespace std;

int func(int n, int x, int y) {
    if (n == 0) return 0;
    int half = 1 << (n - 1);

    // 1번 사각형
    if (x < half && y < half) {
        return func(n - 1, x, y);
    }

    // 2번 사각형
    if (x < half && y >= half) {
        return half * half + func(n - 1, x, y - half);
    }

    // 3번 사각형
    if (x >= half && y < half) {
        return 2 * half * half + func(n - 1, x - half, y);
    }

    // 4번 사각형
    if (x >= half && y >= half) {
        return 3 * half * half + func(n - 1, x - half, y - half);
    }
}

int main(void) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    // 1.입력
    int N, r, c;
    cin >> N >> r >> c;

    cout << func(N, r, c);

    return 0;
}

'알고리즘&자료구조 > 재귀' 카테고리의 다른 글

백준 1992  (0) 2024.03.01
백준 2630  (0) 2024.02.29
백준 1780  (0) 2024.02.27
백준 17478  (0) 2024.02.26
백준 하노이의 탑(11729)  (0) 2024.02.22