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
			
		
	
               
           
					
					
					
					
					
					
				 
								 
								 
								