일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- throwable
- 자바할래
- 함수형 인터페이스
- System.in
- raw 타입
- junit 5
- 스파르타코딩클럽
- 바운디드 타입
- 정렬
- auto.create.topics.enable
- github api
- annotation processor
- System.err
- 자바스터디
- 프리미티브 타입
- docker
- yield
- 브릿지 메소드
- 제네릭 와일드 카드
- 익명 클래스
- Switch Expressions
- 람다식
- 합병 정렬
- 상속
- 로컬 클래스
- System.out
- 제네릭 타입
- 항해99
- Study Halle
- 접근지시자
- Today
- Total
코딩하는 털보
21.09.11 TIL 본문
백준 코딩 문제
https://www.acmicpc.net/problem/2447
2447 별 찍기
재귀적인 패턴으로 별을 찍어 보자. N이 3의 거듭제곱(3, 9, 27, ...)이라고 할 때, 크기 N의 패턴은 N×N 정사각형 모양이다.
크기 3의 패턴은 가운데에 공백이 있고, 가운데를 제외한 모든 칸에 별이 하나씩 있는 패턴이다.
***
* *
***
N이 3보다 클 경우, 크기 N의 패턴은 공백으로 채워진 가운데의 (N/3)×(N/3) 정사각형을 크기 N/3의 패턴으로 둘러싼 형태이다. 예를 들어 크기 27의 패턴은 예제 출력 1과 같다.
첫째 줄에 N이 주어진다. N은 3의 거듭제곱이다. 즉 어떤 정수 k에 대해 N=3^k이며, 이때 1 ≤ k < 8이다.
첫째 줄부터 N번째 줄까지 별을 출력한다.
***************************
* ** ** ** ** ** ** ** ** *
***************************
*** ****** ****** ***
* * * ** * * ** * * *
*** ****** ****** ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
********* *********
* ** ** * * ** ** *
********* *********
*** *** *** ***
* * * * * * * *
*** *** *** ***
********* *********
* ** ** * * ** ** *
********* *********
***************************
* ** ** ** ** ** ** ** ** *
***************************
*** ****** ****** ***
* * * ** * * ** * * *
*** ****** ****** ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
NxN 2차원 배열과 재귀 방식으로 해결하려 했으나, 시간 초과...
public class Q2447 {
static char[][] board;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
board = new char[n][n];
recursive(n, 0, 0, true);
for (int i = 0; i < board.length; i++) {
System.out.println(board[i]);
}
}
public static void recursive(int n, int x, int y, boolean dot) {
if ( n == 1) {
if ( dot ) {
board[x][y] = '*';
} else {
board[x][y] = ' ';
}
} else if ( !dot ) {
recursive(n/3, x, y, false);
recursive(n/3, x + n/3, y, false);
recursive(n/3, x + 2*n/3, y, false);
recursive(n/3, x, y + n/3, false);
recursive(n/3, x + n/3, y + n/3, false);
recursive(n/3, x + 2*n/3, y + n/3, false);
recursive(n/3, x, y + 2*n/3, false);
recursive(n/3, x + n/3, y + 2*n/3, false);
recursive(n/3, x + 2*n/3, y + 2*n/3, false);
} else {
recursive(n/3, x, y, true);
recursive(n/3, x + n/3, y, true);
recursive(n/3, x + 2*n/3, y, true);
recursive(n/3, x, y + n/3, true);
recursive(n/3, x + n/3, y + n/3, false);
recursive(n/3, x + 2*n/3, y + n/3, true);
recursive(n/3, x, y + 2*n/3, true);
recursive(n/3, x + n/3, y + 2*n/3, true);
recursive(n/3, x + 2*n/3, y + 2*n/3, true);
}
}
}
출력 시간이 오래걸리는 것 같아서 BufferedWriter를 사용했더니 통과한다.
package baekjoon;
import java.io.*;
public class Q2447 {
static char[][] board;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(reader.readLine());
board = new char[n][n];
recursive(n, 0, 0, true);
for (int i = 0; i < board.length; i++) {
writer.write(board[i]);
writer.write("\n");
}
writer.flush();
writer.close();
}
public static void recursive(int n, int x, int y, boolean dot) {
if ( n == 1) {
if ( dot ) {
board[x][y] = '*';
} else {
board[x][y] = ' ';
}
} else if ( !dot ) {
recursive(n/3, x, y, false);
recursive(n/3, x + n/3, y, false);
recursive(n/3, x + 2*n/3, y, false);
recursive(n/3, x, y + n/3, false);
recursive(n/3, x + n/3, y + n/3, false);
recursive(n/3, x + 2*n/3, y + n/3, false);
recursive(n/3, x, y + 2*n/3, false);
recursive(n/3, x + n/3, y + 2*n/3, false);
recursive(n/3, x + 2*n/3, y + 2*n/3, false);
} else {
recursive(n/3, x, y, true);
recursive(n/3, x + n/3, y, true);
recursive(n/3, x + 2*n/3, y, true);
recursive(n/3, x, y + n/3, true);
recursive(n/3, x + n/3, y + n/3, false);
recursive(n/3, x + 2*n/3, y + n/3, true);
recursive(n/3, x, y + 2*n/3, true);
recursive(n/3, x + n/3, y + 2*n/3, true);
recursive(n/3, x + 2*n/3, y + 2*n/3, true);
}
}
}
recursive를 여러 갈래로 재귀 호출하는 부분을 반복문으로 만들면 더 깔끔할 것 같다.
public class Q2447 {
static char[][] board;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(reader.readLine());
board = new char[n][n];
recursive(n, 0, 0, true);
for (int i = 0; i < board.length; i++) {
writer.write(board[i]);
writer.write("\n");
}
writer.flush();
writer.close();
}
public static void recursive(int n, int x, int y, boolean dot) {
if ( n == 1) {
if ( dot ) {
board[x][y] = '*';
} else {
board[x][y] = ' ';
}
} else if ( !dot ) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
recursive(n/3, x + i*n/3, y + j*n/3, false);
}
}
} else {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if ( i == 1 && j == 1 ) {
recursive(n/3, x + i*n/3, y + j*n/3, false);
} else {
recursive(n/3, x + i*n/3, y + j*n/3, true);
}
}
}
}
}
}
부녀회장 문제의 아파트때도 그렇고 테이블 같은 느낌의 풀이 과정이 필요할때는 2차원 배열을 빨리 생각해내면 좋을 것 같다.
11729 하노이 탑 이동 순서
https://www.acmicpc.net/problem/11729
세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로 옮기려 한다.
- 한 번에 한 개의 원판만을 다른 탑으로 옮길 수 있다.
- 쌓아 놓은 원판은 항상 위의 것이 아래의 것보다 작아야 한다.
이 작업을 수행하는데 필요한 이동 순서를 출력하는 프로그램을 작성하라. 단, 이동 횟수는 최소가 되어야 한다.
아래 그림은 원판이 5개인 경우의 예시이다.
7
1 3
1 2
3 2
1 3
2 1
2 3
1 3
public class Q11729 {
static List<String> results = new ArrayList<>();
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
int num = Integer.parseInt(reader.readLine());
recursiveTopMove(num,1, 3);
writer.write(results.size()+"\n");
for (String result : results) {
writer.write(result+"\n");
}
writer.flush();
writer.close();
}
private static void recursiveTopMove(int num, int from, int to) {
int bridge = 6-from-to;
if ( num != 1 ) {
recursiveTopMove(num-1, from, bridge);
print(from, to);
recursiveTopMove(num-1, bridge, to);
} else {
print(from, to);
}
}
private static void print(int from, int to) {
results.add(String.valueOf(from)+" "+String.valueOf(to));
}
}
이동 횟수를 더깔끔하게 할 수 없을까 고민중에 원판 수에 따라 규칙이 있다는 것을 알게 되었다.
최소 이동 횟수 = 2^원판수 - 1
위 식을 사용하면 따로 리스트를 만들지 않아도 된다.
import java.io.*;
public class Q11729 {
static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int num = Integer.parseInt(reader.readLine());
writer.write(((int) Math.pow(2, num) - 1) +"\n");
recursiveTopMove(num,1, 3);
writer.flush();
writer.close();
}
private static void recursiveTopMove(int num, int from, int to) throws IOException {
int bridge = 6-from-to;
if ( num != 1 ) {
recursiveTopMove(num-1, from, bridge);
print(from, to);
recursiveTopMove(num-1, bridge, to);
} else {
print(from, to);
}
}
private static void print(int from, int to) throws IOException {
writer.write(String.valueOf(from)+" "+String.valueOf(to)+"\n");
}
}