https://www.acmicpc.net/problem/10994
10994번: 별 찍기 - 19
예제를 보고 규칙을 유추한 뒤에 별을 찍어 보세요.
www.acmicpc.net
풀이
처음 예제 출력을 보면, 1은 별 하나가 찍혀있고, 2는 1의 출력에서 위아래 1줄을 띄고 감싸는 것 같은 모양이다.
별이 찍히는 규칙을 살펴보자면, 일단 가운데 줄을 기준으로 위아래가 대칭이다.
홀수 번째 줄의 경우, 맨 윗줄은 모두 별로 채워져 있고, 그 다음 홀수 번째줄부터 계속 양쪽 사이드에서 별이 1개씩 줄어들고 있다.
짝수 번째 줄의 경우, 처음 줄(위에서 2번째)은 양 끝에 별이 1개씩 있고, 그 다음 짝수 번째줄부터 계속 양쪽 사이드에서 별이 1개씩 추가되고 있다.
위와 같은 규칙을 코드로 구현하면 아래와 같다.
코드
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int size = 4*n-3; // 배열의 가로,세로 크기
char[][] stars = new char[size][size];
// stars 배열을 ' '로 초기화한다.
for (int i = 0; i < size; i++)
Arrays.fill(stars[i], ' ');
// 가운데를 기준으로 대칭이므로 배열의 윗부분만 채운다.
for (int i = 0; i <= size / 2; i++) {
// 첫번째 줄은 모두 별
if (i == 0) {
for (int j = 0; j < size; j++) {
stars[i][j] = '*';
}
}
// 두번째 줄은 양 끝만 별
else if (i == 1) {
stars[i][0] = stars[i][size-1] = '*';
}
else {
// i가 홀수인 경우
// 현재 줄에서 두 줄 위의 줄을 복사한 다음 별을 2개 추가한다.
if (i%2 == 1) {
stars[i] = Arrays.copyOf(stars[i-2], size);
stars[i][i-1] = stars[i][size-i] = '*';
}
// i가 짝수인 경우
// 현재 줄에서 두 줄 위의 줄을 복사한 다음 별을 2개 뺀다.
else {
stars[i] = Arrays.copyOf(stars[i-2], size);
stars[i][i-1] = stars[i][size-i] = ' ';
}
}
}
// 배열의 아랫부분을 채운다.
for (int i = size/2 + 1; i < size; i++) {
stars[i] = Arrays.copyOf(stars[size-1-i], size);
}
// 정답 출력
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++)
sb.append(stars[i][j]);
sb.append("\n");
}
System.out.println(sb);
}
}
- Arrays.fill(stars[i], ' ')
- 일단 먼저 stars 배열을 ' '로 초기화한다. 이 때 주의할 점은 Arrays.fill() 메서드는 일차원 배열만을 인자로 받기 때문에 이차원 배열의 각 줄을 인자로 넘겨야 한다.
- Arrays.copyOf(stars[i-2], size)
- 배열의 내용을 복사하기 위해서 Arrays.copyOf() 메서드를 사용한다.
- 참고: [Java] 자바 배열을 복사하는 다양한 방법 (깊은복사, 얕은복사)
다른 풀이 2
재귀함수를 사용하여 바깥쪽부터 안쪽으로 사각형 테두리를 그리듯이 별을 그린다.
BufferedWriter를 사용해 출력한다.
로직
1. size는 입력받은 숫자 n의 (4n - 3) 이다.
2. Arrays.fill(stars[i], ' ')로 stars 배열을 ' '로 초기화한다.
3. drawStar(0, size)를 호출한다. 이 때 s는 시작 위치, len는 끝 위치다.
4. len == 1이면 리턴하고, 아니면 drawStar(s+2, len-2)를 호출한다.
5. 재귀함수가 종료하면 BufferedWriter를 사용해 정답을 출력한다.
import java.io.*;
import java.util.*;
public class Main {
static int size;
static char[][] stars;
public static void drawStar(int s, int len) {
for (int i = s; i < len; i++) {
stars[s][i] = '*'; // 맨 위 가로줄
stars[len-1][i] = '*'; // 맨 아래 가로줄
stars[i][s] = '*'; // 왼쪽 세로줄
stars[i][len-1] = '*'; // 오른쪽 세로줄
}
if (len == 1)
return;
else
drawStar(s+2, len-2);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
size = 4*n - 3;
stars = new char[size][size];
for (int i = 0; i < size; i++)
Arrays.fill(stars[i], ' ');
drawStar(0, size);
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++)
bw.write(stars[i][j]);
bw.write('\n');
}
bw.flush();
bw.close();
br.close();
}
}
참고: https://baelanche.tistory.com/118
2번째 방법이 메모리와 실행 시간 측면에서 더 좋은 것을 확인할 수 있다. 또한 재귀함수를 사용하는 방법이 더 직관적이고 가독성이 좋다.
'Algorithm 문제 풀이 > 백준' 카테고리의 다른 글
[백준] 20291번 : 파일 정리 - 자바[Java] (1) | 2022.09.11 |
---|---|
[백준] 1987번 : 알파벳 - 자바[Java] (0) | 2022.09.10 |
[백준] 1759번 : 암호 만들기 - 자바[Java] (0) | 2022.09.09 |
[백준] 1244번 : 스위치 켜기 - 자바[Java] (0) | 2022.09.09 |
[백준] 4396번 : 지뢰찾기 - 자바[Java] (0) | 2022.09.09 |