boj2630-풀이
풀이
분할정복, 재귀
시작점$(Start_x, Start_y)$과, 그 종이의 크기$size$가 주어졌을 때, 해당 종이가 같은 색으로 이루어져 있는지 판단해서 색종이의 수를 구하도록 했다.
(전체 탐색)
check : 시작점으로부터 size * size 크기의 종이가 같은 색으로 채워져 있는지 확인
(재귀를 통한 분할+정복)
rec : 시작점으로부터 size * size 크기의 종이가 몇개의 흰 색/파란 색 정사각형 색종이로 나눌 수 있는지 수를 셈
rec에 대한 설명
- 시작점으로부터 size * size 크기의 종이가 같은 색으로 이루어져 있다면, 해당 색의 수를 1, 다른 색을 0으로 묶어서 반환합니다.
- 4분할하여 각 평면의 왼쪽 위 좌표를 기준으로 size / 2 만큼 탐색하여 그 결과를 모두 합하여 반환
주의 : pair<int, int>에서 (y, x)순서로, 그리고 배열에 대해서도 arr[y][x]로 접근했습니다.
구현
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <utility>
using namespace std;
bool check(pair<int, int> start, int size, vector<vector<int>> &board) {
if (size == 1) return true; // <- 없어도 board[start.first][start.second]만 검사해서 true
int color = board[start.first][start.second];
for (int y = start.first; y < start.first + size; y++) {
for (int x = start.second; x < start.second + size; x++) {
if(board[y][x] != color) return false;
}
}
return true;
}
// overload operator +=, pair<int, int>
pair<int, int> operator+=(pair<int, int> &a, pair<int, int> b) {
a.first += b.first;
a.second += b.second;
return a;
}
pair<int, int> rec(pair<int, int> start, int size, vector<vector<int>> &board) {
if (check(start, size, board))
return board[start.first][start.second] == 0 ? make_pair(1, 0) : make_pair(0, 1);
pair<int, int> mid = {start.first + size / 2, start.second + size / 2};
pair<int, int> result = {0, 0};
int next_size = size / 2;
result += rec(start, next_size, board);
result += rec({start.first, mid.second}, next_size, board);
result += rec({mid.first, start.second}, next_size, board);
result += rec(mid, next_size, board);
return result;
}
int main()
{
int n;
cin >> n;
vector<vector<int>> board(n, vector<int>(n, false));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> board[i][j];
pair<int,int> res = rec({0, 0}, n, board);
cout << res.first << '\n' << res.second;
return 0;
}
댓글남기기