백준 2447 별 찍기 - 10 [JAVA]

Ga0·2023년 9월 2일
0

baekjoon

목록 보기
91/137
post-custom-banner

문제 해석

  • 주어지는 수는 3의 거듭제곱인 N이다.

  • N x N으로 별을 주어진 규칙으로 찍으면 된다. (규칙은 찾았지만 코드를 구현할 엄두가 나지 않았다.)

  • 일단, 규칙은 눈으로 보면 딱 알 수 있을 것이다. (규칙은 아래와 같다.)

  • N = 3 => 3의 1승일 때의 규칙을 보면 3x3크기의 배열로 볼 수 있고, 해당 공백 부분은 Array[1][1]에 해당되는 것을 볼 수 있다. (x, y 축으로 딱 중간이다.)

  • N = 9 => 3의 2승일때 규칙을 보면 9x9크기의 배열로 볼 수 있다.

  • N = 27 => 3의 3승일 때 규칙을 보면 27x27로 배열로 볼 수 있다.

  • 위의 규칙의 공통된 점은 가운데 부분을 비운다는 것이다.

  • 그렇다면 N = 27이라고 가정하고 아래와 같은 출력문을 내려고 한다면 어떻게 해야할까?

  먼저 N = 27 일 때 우리는 9개의 블록(N=9인 블록)으로 구분할 수 있다.
  N = 27일때의 공백인 구간을 만족하면 그 구간은 공백으로 채우고
  공백 구간이 아닌 블럭은 재귀호출을 한다.
  다음 3의 거듭제곱인 N = 9 일 때로 넘어가는데
  앞과 같이 9개의 블록으로 구분한 뒤
  공백 구간은 공백 문자로 채우고 공백이 아닌 구간을 다시 재귀 호출을 한다.
  다음은 N = 3 일 때로 가게 될 것이고
  앞과 같은 과정을 계속 반복하다 보면 N = 1 일 때가 오는데, 
  이땐 더 이상 쪼갤 것이 없음으로 과정을 마치면 된다.
  • 간단히 그림으로 나타낸 것이 아래 사진(이미지 출처)과 같다.

코드

import java.io.*;
import java.util.Arrays;

public class Main {

    static char[][] starArray;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        int N = Integer.parseInt(br.readLine()); //3의 거듭제곱

        starArray = new char[N][N]; //별 찍는 배열

        checkStar(0, 0, N, false); //함수 초기 호출(시작 0, 0 크기 N, 공백 아님)

        //별 출력하기
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                sb.append(starArray[i][j]);
            }
            sb.append("\n");
        }
        br.close();
        System.out.println(sb);
    }

    //시작 x축, 시작 y축, 크기 N, 공백 여부
    static void checkStar(int x, int y, int N, boolean blank) {

        //공백일 경우
        if (blank) {
            //시작 점 x, y 부터 해당 구역의 크기 만큼(N)
            for (int i = x; i < x + N; i++) {
                for (int j = y; j < y + N; j++) {
                    starArray[i][j] = ' ';
                }
            }
            return;
        }

        //더이상 쪼갤 수 없을 때
        if(N <= 1){
            //더이상 쪼갤 수 없는 값은 중간 값도 구할 수 없기 때문에 무조건 별(*)
            starArray[x][y] = '*';
            return;
        }

        int blockSize = N/3; //N은 3의 거듭제곱임으로 한 블록의 사이즈를 구하기 위해선  3으로 나눈다
        int startCount = 0; //별 공백 기준을 체크하는 변수, 별 구역 누적

        //구역으로 구분하는 것이므로 증가값이 블록사이즈만큼 증가해야한다.
        for(int i = x; i < x + N; i+=blockSize){
            for(int j = y; j < y + N;j+=blockSize){
                startCount++;
                //N이 3, 9, 27 .. 3의 거듭제곱일 때 9개의 구역을 나눈다.
                // => 9개의 구역으로 나눴을 때 5번째가 무조건 공백이다.
                if(startCount == 5){
                    checkStar(i, j, blockSize, true);
                }else{
                    checkStar(i, j, blockSize, false);
                }
            }
        }
    }
}
  • 코드에 대한 설명은 주석으로 작성해두었다.

결과

느낀 점

  • 이 문제는 진짜 너무 어려웠다. 계속 고민하다가 도저히 풀이를 생각해낼 수가 없어서 설명 잘 해놓은 블로그(참고 풀이 사이트)를 보고 풀이를 했다.
post-custom-banner

0개의 댓글