ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 4256(트리)
    전공/알고리즘 2020. 6. 30. 17:09

    https://www.acmicpc.net/problem/4256

     

    4256번: 트리

    문제 이진 트리는 매우 중요한 기본 자료 구조이다. 아래 그림은 루트 노드가 유일한 이진 트리이다. 모든 노드는 최대 2개의 자식 노드를 가질 수 있으며, 왼쪽 자식이 순서가 먼저이다. 노드 n��

    www.acmicpc.net

     

    이진 트리의 전위, 중위, 후위 순회에 대한 문제다. 

     

    일단 전위 순회의 결과와 중위 순회의 결과로 후위 순회를 구할 수 있도록 문제가 주어진다고 했다. 

     

    그러면 어떻게 전위 순회와 중위 순회로 후위 순회를 구할 수 있을까. 

     

    전위는 방문이 먼저인 VLR구조이고, 중위는 LVR구조이다. 

     

    방문을 먼저한다는게 후위 순회를 위해서 이진트리구조를 알 수 있는 핵심이라고 생각한다. 

     

    무조건 root부터 순회를 시작하는 구조에서 방문을 먼저한다 -> 가장 먼저 출력되는 값 = root

     

    그래서 문제해결방법은 subtree안의 subtree를 계속해서 구하는 방식으로 진행된다.

     

    예시에서

     

    a = 3 2 1 4

    b = 2 3 4 1

     

    이 각각 순회의 결과라고 한다면 3은 무조건 root이다. 

    그러고 중위 순회의 구조를 조사해보면 LVR, 방문이 중간이다. 

     

    여기서는 dfs의 작동원리를 이해하고 있으면 쉽게 이해할 수 있지만 그렇지 않으면 어려울 수도 있다.

     

    방문이 중간이라는 소리는 모든 L-subtree를 조사하고 나서 방문 후 R-subtree를 조사한다는 소리이다. 

    그러므로 중위 순회에서 3의 위치를 기준으로 왼쪽은 L-subtree, 오른쪽은 R-subtree이다. 

     

    따라서 문제는 재귀적으로 진행된다. 

     

    a에서 root를 구함

    root = 3 

    왼쪽에 노드 2가 존재.

    오른쪽에 4, 1이 존재.

     

    subtree로 진행 

    a에서 root를 구함

    root = 2

    왼쪽에 존재 x

    오른쪽에 존재 x

     

    다시 진행 

    a에서 root를 구함

    root = 1

    왼쪽에 4

    오른쪽에 존재 x

     

    이렇게 재귀적으로 진행된다 .

     

    그래서 우리가 해야될 일은 조사 범위를 함수의 매개변수로 넣어서 subtree의 조사범위를 제한시켜준다. 

     

    	solve(l, tmp-1, index+1); 왼쪽 서브트리
    	solve(tmp+1, r, index+tmp-l+1); 오른쪽 서브트리
    

     index의 값을 설정해주는게 꽤 까다로웠는데 그냥 뭐를 구하려고 하는지만 잘 생각해보면 구할 수 있는 것 같다.

     

    이제 언제 후위 연산을 위해서 값을 출력시켜야 할 지 생각해보자

     

    후위 연산은 LRV이다. 따라서 l_subtree와 r_subtree 뒤에 원하는 값을 출력한다. 

     

    #include<iostream>
    using namespace std;
    #define MAX 1001
    
    int T, n;
    int a[MAX];
    int b[MAX];
    
    void solve(int l, int r,  int index) {
    	if (l > r) return;
    	int tmp = b[a[index]];
    	solve(l, tmp-1, index+1);
    	solve(tmp+1, r, index+tmp-l+1);
    	cout << a[index] << " ";
    }
    
    int main() {
    	ios_base::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	cin >> T;
    	for (int i = 0; i < T; i++) {
    		cin >> n;
    		for (int j = 0; j < n; j++) {
    			cin >> a[j];
    		}
    		for (int j = 0; j < n; j++) {
    			int tmp;
    			cin >> tmp;
    			b[tmp] = j;
    		}
    		solve(0, n - 1, 0);
    		cout << "\n";
    	}
    
    	
    }

     

     

    '전공 > 알고리즘' 카테고리의 다른 글

    백준 1068(트리)  (0) 2020.07.01
    백준 2263(트리의 순회)  (0) 2020.07.01
    백준 1967(트리의 지름)  (0) 2020.06.30
    백준 17396(백도어)  (0) 2020.06.30
    백준 13549(숨바꼭질3)  (0) 2020.06.29

    댓글

Designed by Tistory.