https://www.acmicpc.net/problem/1780
1780번: 종이의 개수
N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1의 세 값 중 하나가 저장되어 있다. 우리는 이 행렬을 적절한 크기로 자르려고 하는데, 이때 다음의 규칙에 따라 자르려고 한다. 만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다. (1)이 아닌 경우에는 종이를 같은 크기의 9개의 종이로 자르고, 각각의 잘린 종이에 대해서 (1)의 과정을 반복한다. 이와 같이 종이를 잘랐을 때, -1로만 채워진 종이의 개수, 0으
www.acmicpc.net
분할 정복 문제다. 각 종이의 모든 칸을 탐색한 다음 하나의 숫자만으로 이루어져 있는지 확인하고 그렇지 않다면 종이를 가로와 세로로 3등분 하여 다시 재탐색한다. 기본 문제이니 잘 알아두도록 해야겠다.
#include <iostream>
#include <cmath>
using namespace std;
const int len = 3 * 3 * 3 * 3 * 3 * 3 * 3;
int cnt[3] = { 0, }; //-1, 0, 1중 단 하나만 있는 종이를 세는 변수
int mat[len + 1][len + 1] = { 0, }; //최대 3^7 + 1칸을 가로, 세로로 잡는다.
//분할 정복을 이용한 종이 자르기
void func(int x, int y, int l) {
int num = mat[x][y]; //제일 왼쪽 위에 칸에 적혀 있는 숫자를 저장
bool check = true; //종이에 단 하나의 숫자만 있는지 확인하는 변수, 처음에는 단 하나의 변수만 있다고 가정
//종이에 단 하나의 변수만 있는지 탐색하는 과정
for(int i = x; i < x + l; i++) {
for(int j = y; j < y + l; j++) {
if(num != mat[i][j]) { //다른 숫자가 나오면
check = false; //단 하나의 숫자만 있지 않다고 바꾸고
break; //탈출
}
}
if(!check) { //단 하나의 숫자만 있지 않다면
break; //탈출
}
}
if(check) { //종이에 숫자가 하나인 경우
if(num == -1) { //-1만 있는 경우
cnt[0]++;
}
else if(num == 0) { //0만 있는 경우
cnt[1]++;
}
else { //1만 있는 경우
cnt[2]++;
}
}
else { //그 외의 경우는 3등분하여 재탐색(분할)
func(x, y, l / 3);
func(x, y + l / 3, l / 3);
func(x, y + (l / 3) * 2, l / 3);
func(x + l / 3, y, l / 3);
func(x + l / 3, y + l / 3, l / 3);
func(x + l / 3, y + (l / 3) * 2, l / 3);
func(x + (l / 3) * 2 , y, l / 3);
func(x + (l / 3) * 2, y + (l / 3), l / 3);
func(x + (l / 3) * 2, y + (l / 3) * 2, l / 3);
}
}
int main() {
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
cin >> mat[i][j];
}
}
func(1, 1, n); //탐색 시작, 처음 위치는 맨 왼쪽 맨 위에서 길이 n으로 탐색 시작
for(int i = 0; i < 3; i++) {
cout << cnt[i] << '\n';
}
}
'백준' 카테고리의 다른 글
백준11559 - Puyo Puyo (0) | 2020.04.09 |
---|---|
백준1325 - 효율적인 해킹 (0) | 2020.04.08 |
백준14938 - 서강그라운드 (0) | 2020.04.05 |
백준15723 - n단 논법 (0) | 2020.04.03 |
백준16401 - 과자 나눠주기 (0) | 2020.04.02 |