백준 : 분할정복

백준 : 프렉탈 평면(1030) with 자바

유민기 2023. 9. 15. 14:45

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

 

1030번: 프렉탈 평면

첫째 줄에 7개의 정수 s, N, K, R1, R2, C1, C2가 주어진다.

www.acmicpc.net

이문제는 s,N, K, R1, R2, R3, R4를 입력받은 뒤 범위만큼의 프렉탈 크기를 출력하면된다.

s = 반복횟수

N = 프렉탈의 크기

K = 검은색(1) 크기

R1, R2 = 행의 크기

C1, C2 = 열의 크기

 

예제를 보면서 설명하겠다.

예제 입력 1 복사

1 5 3 0 4 0 4

 

예제 입력 2 복사

2 3 1 0 8 0 8

 

예제 입력 3 복사

3 3 1 4 11 5 10

 

 
import java.util.Scanner;

public class 프렉탈평면 {
      static int s, N, K, R1, R2, C1, C2;

      // 재귀 함수로 해당 위치가 1인지 0인지 계산하는 함수
      static int func(int size, int x, int y) {
            if (size == 1) return 0;
                int border = size / N;
                if (x >= border * (N - K) / 2 && x < border * (N + K) / 2 &&
                     y >= border * (N - K) / 2 && y < border * (N + K) / 2) {
                     return 1;
                }
               return func(border, x % border, y % border);
            }

       public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
       s = sc.nextInt(); // 반복 횟수
       N = sc.nextInt(); // 프렉탈 크기
       K = sc.nextInt(); // 검은 부분 크기
       R1 = sc.nextInt(); // 출력할 행 범위 시작
       R2 = sc.nextInt(); // 출력할 행 범위 끝
       C1 = sc.nextInt(); // 출력할 열 범위 시작
       C2  = sc.nextInt(); // 출력할 열 범위 끝

       if (s == 0) {
           System.out.println(0);
           return;
       }

       int size = 1;
       while (s-- > 0) {
       size *= N;
       }

       for (int i = R1; i <= R2; i++) {
             for (int j = C1; j <= C2; j++) {
                   System.out.print(func(size, i, j));
             }
             System.out.println();
       }
    }
}

코드를 하나씩 분석해보자.

일단 문제에서 정의한 변수들을 전역변수로 만들어준다.

그리고 func함수를 만들어서 현재 size가 0인지 1인지를 판별할것이다.

만약 size가 1일 경우 0을 반환해준다,

border변수를 생성하고 size를 N(프렉탈의 크기)만큼 나누어준다.

만약 x가 boder * (프렉탈의 크기 - 검은부분의 크기) / 2 이고 x < border * (프렉탈 크기 * 검은부분 크기) / 2 이고

        y가 boder * (프렉탈의 크기 - 검은부분의 크기) / 2 이고 y < border * (프렉탈 크기 * 검은부분 크기) / 2이라면

        1을 반환한다.

size의 크기를 판별했다면 조건문을 종료하고 재귀를 통해 border, x %border, y % border를 해준다.

문제에서 정의 된대로 스캐너를 생성해주고 변수를 선언한 뒤, 차례대로 읽어들여줍니다.

s(반복횟수)가 0이라면 재귀를 할필요가 없으므로 0을 출력하고 종료합니다.

size변수를 선언한 뒤 1을 할당합니다.

반목문을 돌려서 s가 0보다 클경우 s--를 해준 뒤 size에 N을 곱해줍니다.

이과정을 0보다 작아질 때까지 반복해줍니다.

마지막 출력부분입니다.  반복문을 사용하여 {R1(행 시작) ~ R2(행 끝)} * {C1(열 시작) ~ C2(열 끝)}까지 반복한 뒤 재귀로 계산한 func함수를 불러와서 출력합니다.

println()을 바깥쪽 반복문에 배치한 이유는 행의 출력이 끝난 뒤 줄바꿈을 해주기 위함입니다.