티스토리 뷰

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

 

2447번: 별 찍기 - 10

첫째 줄에 N이 주어진다. N은 항상 3의 제곱꼴인 수이다. (3, 9, 27, ...) (N=3k, 1 ≤ k < 8)

www.acmicpc.net


 

  • 어떻게 풀까?

27을 입력했을 때의 출력

 위의 이미지에서 검은색 동그라미를 친부분이 3을 입력했을 때 나오는 그림이다.

 9를 입력했을때는 빨간선으로 나눠진 아홉칸 중 비어있는 가운데가 아닌 한칸이 출력된다.

 

이미지를 보고 대충의 규칙이 있다는 것은 알 수 있지만 코드로는 어떻게 나타낼 수 있을까?

 

 

* * *
*   *
* * *

항상 위의 표와 같이, 크게 아홉칸으로 나눌 수 있으며 가운데는 비어있다는 것을 사진을 통해 확인했다. 이는 3x3인 배열에서는 [1][1]만 비어있는 것이라고 볼 수있다.

 

 for문 두개를 돌려 가운데는 ' '를 집어 넣는 식으로 표현할 수 있을것이다. 

1
2
3
4
5
6
for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i == 1 && j == 1) ary[i][j] = ' ';
                else ary[i][j]='*';
            }
        }

 

위의 식대로만 돌리면 항상 3x3이기 때문에 문제의 9,27...등의 큰수를 받았을 때는 원하는 결과를 출력하지 않을 것이다. 따라서 한칸일 때만 ' '나 '*'를 집어넣을 수 있도록 조건을 추가해야한다.

 

따로 makeSrarArray라는 함수를 만들어 인덱스와 크기를 넘기기로 한다. 

(인덱스 ->> 어떤 인덱스에 별인지 ' '인지를 넣어야하기때문에 매개변수로 넘겨줘야한다.)

(크기   ->> 크기=1일 때만 값을 넣을 수 있도록 크기체크를 위해 항상 넘겨줘야한다.)

 

또한 크기가 1이기 이전에 크게 구등분으로 나눠있을 때의 가운데 칸인 [1][1]일 경우에는 해당 칸이 전부 ' '이 들어가도록 해야한다. 즉, [1][1]일 경우엔 '*'을 집어넣지 못하도록 함수를 호출하지 말아야한다. 출력배열 ary의 초기값을 ' '로 둔채 '*'인 경우만 함수를 호출해 배열에 값을 넣도록 만들어보자. 

 

for문 두개를 돌릴 때 (구등분으로 나누는 부분) 가운데([1][1])일 경우에는 함수를 호출하지않고 넘긴다.

(왜? 호출을 넘김으로써 해당칸에는 전부 ' '로 초기화된 값이 남겨져있을 것이기 때문이다.)

 

나머지인 경우에만 함수를 호출하며 크기가 1일경우엔 무조건 *을 넣는다.

 

이상 아래와 같은 함수를 만들 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void makeStarArray(int x,int y,int num){
 
        if(num == 1){
            ary[x][y] = '*';
            return;
        }
 
        int value = num/3;
 
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i == 1 && j == 1) ;
                else makeStarArray(?,?,value);
            }
        }
    }

 

makeStarArray의 첫번째와 두번째 매개변수에 들어갈 인덱스는 어떻게 구할 수 있을까?

1 2 3
4 5 6
7 8 9

위 함수의 for문 두개가 구등분한 것을 표현한 것이므로 [0][0]은 1번칸, [0][1]는 2번칸... 을 나타낸다.

즉 x+(value*i), y+(value*j)로 해당칸의 가장왼쪽이며 위인 인덱스(size>1) or 해당 인덱스(size=1)를 표현 할 수 있을 것이다.

 

예를 들어 9x9일경우 [0][0]일땐 makeStarArray(0,0,3)을 호출하며, 호출된 함수 안에서 크기가 1인 makeStarArray함수에 의해 가운데 ary[1][1]을 제외한 1번칸의 나머지 배열에 '*'이 들어간다. 다음으론 구등분한 칸의 [0][1]인 2칸에 대해 동작한다. 이땐 makeStarArray(0,3,3)이 호출되며, 크기가 1인 makeStarArray함수가 여덟번 호출되어에 가운데인 ary[1][4]를 제외한 2번칸의 나머지 여덟개 배열에 '*'이 들어간다.

 

이런식으로 반복되는 부분을 찾고 규칙을 만들어 문제를 해결할 수 있다.

 

 

  • 구현 중 만난 문제/해결

자바 char 배열을 초기화 할 때의 값은 자동으로 null이다. 따라서 출력엔 빈값으로 나온것처럼 보여 그냥 제출할 수 있겠지만, 실제로 제출하면 틀린다. 초기값으로 ' '를 입력해주지않으면 안된다.

 

 

  • 구현

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import java.util.Arrays;
import java.util.Scanner;
 
public class Main {
     
    public static char[][] ary;
 
    public static void makeStarArray(int x,int y,int num){
 
        if(num == 1){
            ary[x][y] = '*';
            return;
        }
 
         
        int value = num/3;
 
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i == 1 && j == 1);
                else makeStarArray(x+(value*i), y+(value*j), value);
            }
        }
    }
 
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        StringBuilder sb = new StringBuilder();
        int size = Integer.parseInt(sc.nextLine());
        ary = new char[size][size];
         
        for(int i=0;i<size;i++){
            Arrays.fill(ary[i], ' ');
        }
        makeStarArray(0,0,size);
 
        for(int i=0;i<size;i++){
            for(int j=0;j<size;j++){
                sb.append(ary[i][j]);
            }
            sb.append("\n");
        }
 
        System.out.println(sb.toString());
    }
}

'Algorithm > 백준(baekjoon)' 카테고리의 다른 글

[백준]1015번: 수열 정렬  (0) 2019.07.05
[백준]1074번: Z  (0) 2019.07.02
[백준]11729번: 하노이 탑 이동 순서  (0) 2019.06.24
[백준]1436번: 영화감독 숌  (0) 2019.06.19
[백준]1107번: 리모컨  (0) 2019.06.18
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함