티스토리 뷰
[Java+Python]2630번, 색종이 만들기
Vagabund.Gni 2023. 6. 5. 12:31목차
분할 정복 단계
문제
아래 <그림 1>과 같이 여러 개의 정사각형칸들로 이루어진 정사각형 모양의 종이가 주어져 있고,
각 정사각형들은 하얀색으로 칠해져 있거나 파란색으로 칠해져 있다.
주어진 종이를 일정한 규칙에 따라 잘라서 다양한 크기를 가진 정사각형 모양의 하얀색 또는 파란색 색종이를 만들려고 한다.
전체 종이의 크기가 $N×N$($N=2^k$, $k$는 1 이상 7 이하의 자연수)이라면 종이를 자르는 규칙은 다음과 같다.
- 전체 종이가 모두 같은 색으로 칠해져 있지 않으면 가로와 세로로 중간 부분을 잘라서
<그림 2>의 I, II, III, IV와 같이 똑같은 크기의 네 개의 N/2 × N/2 색종이로 나눈다. - 나누어진 종이 I, II, III, IV 각각에 대해서도 앞에서와 마찬가지로 모두 같은 색으로 칠해져 있지 않으면
같은 방법으로 똑같은 크기의 네 개의 색종이로 나눈다. - 이와 같은 과정을 잘라진 종이가 모두 하얀색 또는 모두 파란색으로 칠해져 있거나,
하나의 정사각형 칸이 되어 더 이상 자를 수 없을 때까지 반복한다.
위와 같은 규칙에 따라 잘랐을 때,
- <그림 3>은 <그림 1>의 종이를 처음 나눈 후의 상태를,
- <그림 4>는 두 번째 나눈 후의 상태를,
- <그림 5>는 최종적으로 만들어진 다양한 크기의 9장의 하얀색 색종이와 7장의 파란색 색종이를 보여주고 있다.
입력으로 주어진 종이의 한 변의 길이 N과 각 정사각형칸의 색(하얀색 또는 파란색)이 주어질 때
잘라진 하얀색 색종이와 파란색 색종이의 개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에는 전체 종이의 한 변의 길이 N이 주어져 있다.
N은 2, 4, 8, 16, 32, 64, 128 중 하나이다.
색종이의 각 가로줄의 정사각형칸들의 색이 윗줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다.
하얀색으로 칠해진 칸은 0, 파란색으로 칠해진 칸은 1로 주어지며, 각 숫자 사이에는 빈칸이 하나씩 있다.
출력
첫째 줄에는 잘라진 햐얀색 색종이의 개수를 출력하고, 둘째 줄에는 파란색 색종이의 개수를 출력한다.
풀이
정해진 규칙에 따라 색종이를 자르되, 잘라진 종이가 모두 같은 색으로 칠해져 있다면 멈추고 개수를 세는 문제이다.
문제가 길지만 사실 별 내용은 없고, 주어진 규칙에 맞게 종이를 분할해 확인하는 재귀함수를 구성하면 된다.
풀이 알고리즘은 대략 아래와 같다.
- 입력으로 주어진 색종이의 한 변의 길이 n을 저장하고 이를 이용해 n x n 이차원 배열(리스트) board를 초기화한다.
- 이어서 재귀함수 quadrant를 호출한다. 해당 함수의 작동 방식은 아래와 같다.
- isSame 메서드를 호출해 현재 분할 영역이 전부 같은 색인지 확인한다.
- 모든 영역이 같은 색이라면 해당 색상의 카운트를 증가시킨다.
- 그렇지 않다면 자기 자신을 네 번 호출해 동일한 크기를 가진 네 개의 영역으로 분할해 확인한다.
- 모든 영역이 같은 색이 될 때까지 반복한다.
- 저장된 색종이의 개수 white와 blue를 순서대로 출력한다.
재귀호출을 이용한 백트래킹 등의 알고리즘에 익숙하다면 코드가 다소 길 뿐이지 알고리즘 자체는 간단하다.
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Prob2630 {
static int[][] board;
static int white = 0;
static int blue = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
board = new int[n][n];
for (int i = 0; i < n; i++) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < n; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
quadrant(0, 0, n);
System.out.println(white);
System.out.println(blue);
}
private static void quadrant(int row, int col, int size) {
if (isSame(row, col, size)) {
if (board[row][col] == 0) {
white++;
return;
} else {
blue++;
return;
}
}
int newSize = size / 2;
quadrant(row, col, newSize);
quadrant(row, col + newSize, newSize);
quadrant(row + newSize, col, newSize);
quadrant(row + newSize, col + newSize, newSize);
}
private static boolean isSame(int row, int col, int size) {
int color = board[row][col];
for (int i = row; i < row + size; i++) {
for (int j = col; j < col + size; j++) {
if (board[i][j] != color) {
return false;
}
}
}
return true;
}
}
Python
import sys
n = int(sys.stdin.readline().rstrip())
white = 0
blue = 0
board = [list(map(int, sys.stdin.readline().rstrip().split())) for _ in range(n)]
def is_same(row, col, size):
color = board[row][col]
for i in range(row, row + size):
for j in range(col, col + size):
if board[i][j] != color:
return False
return True
def quadrant(row, col, size):
global white, blue
if is_same(row, col, size):
if board[row][col] == 0:
white += 1
return
else:
blue += 1
return
new_size = size // 2
quadrant(row, col, new_size)
quadrant(row, col + new_size, new_size)
quadrant(row + new_size, col, new_size)
quadrant(row + new_size, col + new_size, new_size)
quadrant(0, 0, n)
print(white)
print(blue)
Performance
'Algorithm > [Java+Python+JavaScript]BackJoon' 카테고리의 다른 글
[Java+Python]1629번, 곱셈 (0) | 2023.06.08 |
---|---|
[Java+Python]1780번, 종이의 개수 (0) | 2023.06.07 |
[Java+Python]1992번, 쿼드 트리 (1) | 2023.06.06 |
[Java+Python]13305번, 주유소 (1) | 2023.06.04 |
[Java+Python]1541번, 잃어버린 괄호 (0) | 2023.06.02 |
[Java+Python]11339번, ATM (0) | 2023.05.31 |
- Total
- Today
- Yesterday
- spring
- Python
- 맛집
- 백준
- 칼이사
- 세계일주
- BOJ
- a6000
- 면접 준비
- 리스트
- 야경
- 지지
- 파이썬
- 기술면접
- Algorithm
- 유럽여행
- 스프링
- 알고리즘
- 남미
- 스트림
- 유럽
- 여행
- 자바
- 중남미
- Backjoon
- 동적계획법
- java
- 세모
- RX100M5
- 세계여행
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |