KoreanFoodie's Study
[종만북 문제] 쿼드 트리 뒤집기 (문제 ID : QUADTREE, 난이도 : 하) 본문
Data Structures, Algorithm/종만북
[종만북 문제] 쿼드 트리 뒤집기 (문제 ID : QUADTREE, 난이도 : 하)
GoldGiver 2024. 3. 5. 19:37
프로그래밍 대회에서 배우는 알고리즘 문제해결 전략(이하 종만북)에서 소개된 문제를 풀이합니다. 알고리즘에 진심이시라면, 직접 구매하셔서 읽어보시는 것을 추천합니다!
핵심 :
1. 단순하게 생각해라
[종만북 문제] 쿼드 트리 뒤집기 (문제 ID : QUADTREE, 난이도 : 하)
음.. 쿼드 트리는 대량의 좌표 데이터를 메모리 안에 압축해 저장하기 위해 사용하는 여러 기법 중 하나이다. 쿼드 트리는 주어진 공간을 항상 4개로 분할하여 재귀적으로 저장하는데, 이번에는 검은색/흰색밖에 없는 그림을 압축한 예제를 풀어 볼 것이다. 😎
일단 단순히 재귀적으로만 풀면, 아래와 같이 풀어볼 수도 있다(책에 나온 버전은 그 다음에 소개할 것임).
#include <iostream>
#include "stdlib.h"
#include <vector>
using namespace std;
#define MINVAL(x, y) (((x) > (y)) ? y : x)
#define MAXVAL(x, y) (((x) > (y)) ? x : y)
/****************************************************************************************************/
/****************************************************************************************************/
/****************************************************************************************************/
struct node
{
char c;
vector<node*> children;
node() = default;
node(node* newNode)
{
c = newNode->c;
for (int i = 0; i < newNode->children.size(); ++i)
{
children.push_back(new node(newNode->children[i]));
}
}
};
string ans;
vector<char> inputs;
node* head;
node* makeTree(node* parent, int& idx)
{
if (inputs.size() <= idx)
return parent;
if (parent->c == 'x')
{
for (int i = 0; i < 4; ++i)
{
node* child = new node;
child->c = inputs[++idx];
parent->children.push_back(makeTree(child, idx));
}
}
return parent;
}
void reverseTree(node* cur)
{
if (nullptr == cur)
return;
if (cur->c == 'x')
{
for (int i = 0; i < 4; ++i)
reverseTree(cur->children[i]);
node* temp1 = cur->children[0];
node* temp2 = cur->children[1];
cur->children[0] = cur->children[2];
cur->children[1] = cur->children[3];
cur->children[2] = temp1;
cur->children[3] = temp2;
}
}
void printTree(node* cur)
{
if (nullptr == cur)
return;
cout << cur->c;
for (int i = 0; i < cur->children.size(); ++i)
printTree(cur->children[i]);
}
void sol()
{
head = new node;
head->c = inputs[0];
int idx = 0;
makeTree(head, idx);
reverseTree(head);
printTree(head);
cout << endl;
}
void outputHandler()
{
sol();
}
void inputHandler()
{
inputs.clear();
string input;
cin >> input;
for (char c : input)
inputs.push_back(c);
}
int main()
{
int cases;
cin >> cases;
while (cases--)
{
inputHandler();
outputHandler();
}
return 0;
}
그냥 makeTree 로 트리 구조를 만들고, reverseTree 로 재귀적으로 child 노드들을 뒤집으면 해결이 된다.
그런데, 그랜드 소드 마스터 구종만 선생님은 이 문제를 어떻게 푸셨을까? 일단, 다음과 같이 crude 한 압축 해제 구현을 만들어 볼 수 있다. 아래 코드는 문자열을 나눠가면서 압축 해제한다.
constexpr int MAX_SIZE = 1000;
char decompressed[MAX_SIZE][MAX_SIZE];
void decompress(string::iterator& it, int y, int x, int size)
{
// 한 글자를 검사할 때마다 반복자를 한 칸 앞으로 옮긴다.
char head = *(it++);
// 기저 사례 : 첫 글자가 b 또는 w 인 경우
if (head == 'b' || head == 'w')
{
for (int dy = 0; dy < size; ++dy)
for (int dx = 0; dx < size; ++dx)
decompressed[y+dy][x+dx] = head;
}
else
{
// 네 부분을 각각 순서대로 압축 해제한다.
int half = size / 2;
decompress(it, y, x, half);
decompress(it, y, x + half, half);
decompress(it, y + half, x, half);
decompress(it, y + half, x + half, half);
}
}
그런데 사실, 결과를 굳이 저장하지 않고 reverse 라는 함수 하나로도 풀 수 있다.
#include <iostream>
#include "stdlib.h"
#include <vector>
using namespace std;
string reverse(string::iterator& it)
{
char head = *it;
++it;
if (head == 'b' || head == 'w')
return string(1, head);
string upperLeft = reverse(it);
string upperRight = reverse(it);
string lowerLeft = reverse(it);
string lowerRight = reverse(it);
// 각각 위와 아래 조각들의 위치를 바꾼다
return string("x") + lowerLeft + lowerRight + upperLeft + upperRight;
}
void sol()
{
string input;
cin >> input;
auto itr = input.begin();
cout << reverse(itr) << endl;
}
int main()
{
int cases;
cin >> cases;
while (cases--)
{
sol();
}
return 0;
}
아, 이거 ㄹㅇ 실화냐? 구종만 선생님은 전설이다. 진짜 세계관최강자의 코드다...
'Data Structures, Algorithm > 종만북' 카테고리의 다른 글
[종만북 문제] 팬미팅 (문제 ID : FANMEETING, 난이도 : 상) (1) | 2024.03.06 |
---|---|
[종만북 문제] 울타리 잘라내기 (문제 ID : FENCE, 난이도 : 중) (1) | 2024.03.05 |
[종만북 문제] Synchronizing Clocks, 시계 맞추기 (문제 ID : CLOCKSYNC, 난이도 : 중) (0) | 2024.03.04 |
[종만북 문제] 게임판 덮기 (문제 ID : BOARDCOVER, 난이도 : 하) (0) | 2024.03.04 |
[종만북 문제] 소풍 (문제 ID : PICNIC, 난이도 : 하) (0) | 2024.03.03 |
Comments