주어진 영상을 4등분하여 각각의 영역에 대해 압축을 한다.
이 때 해당 영역이 모두 같은 숫자면 바로 압축하고, 영역의 숫자들이 다르면 또 다시 4등분하여 과정을 반복한다.
크기가 1이 되면 무조건 해당 원소를 리턴한다.
문제 풀이
#include <iostream>
#include <vector>
using namespace std;
vector<char> result;
void compress(int n, vector< vector<int> >& video) {
//base case : 사이즈가 1이면 해당값 바로 리턴
if (n == 1) {
result.push_back(video[0][0]+'0');
return;
}
// base case : 해당 파트의 모든 원소가 같으면 해당값 리턴
int check = video[0][0]; // 영상의 첫번째 원소와 다른 원소들을 비교
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (video[i][j] != check) { // 첫번째 원소와 값이 다르면 check값 변경시킴
check++;
break;
}
}
if (check != video[0][0]) break;
}
if (check == video[0][0]) { // check값이 변화가 없이 첫번째 원소값을 저장하고 있으면 모든 원소가 같은값임
result.push_back(check+'0');
return;
}
int half = n / 2;
vector< vector<int> > halfVd; // 4등분한 영상
for (int i = 0; i < half; i++) {
vector<int> element(half);
halfVd.push_back(element);
}
// 입력받은 영상을 4등분해서 각 영역에 대해 압축을 실행한다.
result.push_back('(');
for (int domain = 0; domain < 4; domain++) {
// halfVd에 4등분한 해당 영역을 복사한다.
for (int i = 0; i < half; i++) {
for (int j = 0; j < half; j++) {
if (domain == 0) halfVd[i][j] = video[i][j];
else if (domain == 1) halfVd[i][j] = video[i][j + half];
else if (domain == 2) halfVd[i][j] = video[i + half][j];
else halfVd[i][j] = video[i + half][j + half];
}
}
compress(half, halfVd);
}
result.push_back(')');
}
int main() {
int n;
vector< vector<int> > input;
cin >> n;
// 이중 벡터 동적 할당
for (int i = 0; i < n; i++) {
vector<int> element(n);
input.push_back(element);
}
// 영상 입력받음
for (int i = 0; i < n; i++) {
char line[64];
cin >> line;
for (int j = 0; j < n; j++) {
input[i][j] = line[j] - '0';
}
}
compress(n, input);
for (int i = 0; i < result.size(); i++) {
cout << result[i];
}
cout << endl;
return 0;
}
쿼드 트리 뒤집기 문제
이 문제의 경우 압축되어 있는 문자열을 압축을 풀어 그림을 다시 만든 후, 상하로 뒤집은 그림을 다시 압축해야한다.
그런데 그림의 사이즈가 최대 2^20 * 2^20 까지 될 수 있으므로, 그림의 크기가 커질 경우에는 압축을 다 푸는 것이 불가능하다.
따라서 압축을 풀지않고 문제를 해결하도록 한다.
// 쿼드 트리 뒤집기 문제를 해결하는 분할 정복 알고리즘
string reverse(string::iterator& it){
char head = *it;
it++; // 다음 위치를 가리키게 한다.
// base case : 현재 가리키고 있는 원소가 b 또는 w 이면 그 원소를 리턴한다.
if(head == 'b' || head == 'w') return string(1, head);
// 현재 가리키고 있는 원소가 x 이면 뒤의 문자열들을 네 부분으로 나눈다.
string upperLeft = reverse(it);
string upperRight = reverse(it);
string lowerLeft = reverse(it);
string lowerRight = reverse(it);
// 각각 상하를 반전시킨다.
return string("x") + lowerLeft + lowerRight + upperLeft + upperRight;
}
'DEVELOP > 알고리즘' 카테고리의 다른 글
3. Dynamic Programming (0) | 2019.01.21 |
---|---|
2. Divide & Conquer - 히스토그램에서 가장 큰 직사각형 문제 (6549) (0) | 2019.01.17 |
2. Divide & Conquer - 카라츠바(karatsuba) 알고리즘 (0) | 2019.01.16 |
2. Divide & Conquer (0) | 2019.01.15 |
1. Brute-Force - TSP 문제 알고리즘 (0) | 2019.01.15 |