티스토리 뷰
Algorithm/[Java+Python+JavaScript]BackJoon
[Java+Python]1780번, 종이의 개수
Vagabund.Gni 2023. 6. 7. 10:18728x90
반응형
목차
분할 정복 단계
문제
N×N크기의 행렬로 표현되는 종이가 있다.
종이의 각 칸에는 -1, 0, 1 중 하나가 저장되어 있다.
우리는 이 행렬을 다음과 같은 규칙에 따라 적절한 크기로 자르려고 한다.
- 만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다.
- 1. 이 아닌 경우에는 종이를 같은 크기의 종이 9개로 자르고, 각각의 잘린 종이에 대해서 1. 의 과정을 반복한다
이와 같이 종이를 잘랐을 때,
- -1로만 채워진 종이의 개수,
- 0으로만 채워진 종이의 개수,
- 1로만 채워진 종이의 개수
를 구해내는 프로그램을 작성하시오.
입력
첫째 줄에 $N$($1 ≤ N ≤ 3^7$, $N$은 $3^k$ 꼴)이 주어진다. 다음 $N$개의 줄에는 $N$개의 정수로 행렬이 주어진다.
출력
첫째 줄에 -1로만 채워진 종이의 개수를, 둘째 줄에 0으로만 채워진 종이의 개수를, 셋째 줄에 1로만 채워진 종이의 개수를 출력한다.
풀이
이전 두 문제에서 연습한 분할정복 알고리즘을 아홉 조각으로 늘린 문제이다.
비슷한 문제가 세 개째니까 바로 문제 해결을 위한 알고리즘을 정리하자.
- 입력으로 주어진 영상의 한 변의 길이 n을 저장하고 이를 이용해 n x n 이차원 배열(리스트) paper를 초기화한다.
- -1, 0, 1의 개수를 저장할 크기가 3인 count를 생성 및 초기화해 준다.
- 재귀함수 quadrant를 호출한다. 해당 함수의 작동 방식은 아래와 같다.
- isSame 메서드를 호출해 현재 분할 영역이 전부 같은 값인지 확인한다.
- 전부 같은 값이라면 count[paper[row][col] + 1]의 값을 +1 해준다.
- 여기서 count의 인덱스가 <paper[row][col] + 1>인 이유는 -1, 0, 1을 각각 0, 1, 2 인덱스에 저장하기 위함이다.
- 전부 같은 값이 아니라면 한 변의 길이를 3으로 나눈 뒤 9등분해서 재귀호출을 진행한다.
- 모든 영역이 같은 값을 가질 때까지 반복한다.
- -1, 0, 1의 개수를 차례대로 출력한다.
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Prob1780 {
static int[][] paper;
static int[] count = new int[3];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
paper = new int[n][n];
for (int i = 0; i < n; i++) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < n; j++) {
paper[i][j] = Integer.parseInt(st.nextToken());
}
}
divide(0, 0, n);
for (int i = 0; i < 3; i++) {
System.out.println(count[i]);
}
}
private static void divide(int row, int col, int size) {
if (isSame(row, col, size)) {
count[paper[row][col] + 1]++;
return;
}
int newSize = size / 3;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
divide(row + newSize * i, col + newSize * j, newSize);
}
}
}
private static boolean isSame(int row, int col, int size) {
int color = paper[row][col];
for (int i = row; i < row + size; i++) {
for (int j = col; j < col + size; j++) {
if (paper[i][j] != color) {
return false;
}
}
}
return true;
}
}
Python
import sys
n = int(sys.stdin.readline().rstrip())
paper = [list(map(int, sys.stdin.readline().rstrip().split(" "))) for _ in range(n)]
count = [0] * 3
def is_same(row, col, size):
color = paper[row][col]
for i in range(row, row + size):
for j in range(col, col + size):
if paper[i][j] != color:
return False
return True
def divide(row, col, size):
if is_same(row, col, size):
count[paper[row][col] + 1] += 1
return
new_size = size // 3
for i in range(3):
for j in range(3):
divide(row + new_size * i, col + new_size * j, new_size)
divide(0, 0, n)
print(*count, sep='\n')
Performance
반응형
'Algorithm > [Java+Python+JavaScript]BackJoon' 카테고리의 다른 글
[Java+Python]2740번, 행렬 곱셈 (0) | 2023.06.12 |
---|---|
[Java+Python]11401번, 이항 계수 3 (0) | 2023.06.11 |
[Java+Python]1629번, 곱셈 (0) | 2023.06.08 |
[Java+Python]1992번, 쿼드 트리 (1) | 2023.06.06 |
[Java+Python]2630번, 색종이 만들기 (2) | 2023.06.05 |
[Java+Python]13305번, 주유소 (1) | 2023.06.04 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 맛집
- 세모
- Backjoon
- 야경
- 파이썬
- 세계일주
- spring
- 스프링
- 스트림
- 동적계획법
- 자바
- 백준
- 알고리즘
- 여행
- 남미
- 리스트
- RX100M5
- 유럽
- a6000
- 중남미
- 지지
- BOJ
- 유럽여행
- 세계여행
- java
- Python
- 면접 준비
- 칼이사
- 기술면접
- Algorithm
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함