알고리즘

소프티어 5회 기출 - 업무 처리

person456 2024. 3. 21. 08:54

난이도 - Lv3

사용 개념 - 구현, 자료구조( 다중 Queue)

풀이 시간 -  40분 ( 설계 25분, 구현 15분 )

핵심 키워드

1. 말단 직원은 왼쪽, 오른쪽의 구분이 없이 하루에 하나씩 업무를 처리한다.

2. 중간직원과 부서장은 홀수 날에는 왼쪽 직원이 보낸 업무를, 짝수 날에는 오른쪽 직원이 보낸 업무를 처리한다.

-> 말단 직원이 일을 올려보내고 하루가 지나야 상사들이 일을 시작할 수 있음.

-> 부서는 완전 이진트리로 되어있기 때문에 트리를 구현하면 가능함.

3. 왼쪽, 오른쪽의 구분이 있기 때문에 Queue[][] 2차원 배열을 사용하여 각 사원들이 왼쪽업무, 오른쪽 업무를 가져갈 수 있게끔 하였음.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.Array;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static StringTokenizer st;
    static StringBuilder sb;
 
    public static void main(String[] args)throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        st = new StringTokenizer(br.readLine(), " ");
        int h = Integer.parseInt(st.nextToken()); // 트리의 높이
        int k = Integer.parseInt(st.nextToken()); // 업무의 수  1명당 맡은 업무의 수임.
        int r = Integer.parseInt(st.nextToken()); // 날의 수
        int width = (int)Math.pow(2, h); // 말단 직원의 수
        int n = (int)Math.pow(2, h+1)-1// 전체 노드의 수
        Queue<Integer>[][] queues = new Queue[n][2];
        for(int i=0; i<n; i++){
            for(int j=0; j<2; j++){
                queues[i][j] = new ArrayDeque<>();
            }
        }
 
        for(int i=n-width; i<n; i++){
            st = new StringTokenizer(br.readLine(), " ");
            for(int j=0; j<k; j++){
                queues[i][0].offer(Integer.parseInt(st.nextToken())); // 말단들은 왼쪽 오른쪽 구분이 없단다
            }
        }
 
        int result = 0;
        int day = 1;
        while(day<=r){
            int bit = day%2;
            if(bit==1 && !queues[0][0].isEmpty()){ // 홀수 날? 그럼 왼쪽 처리
                result+=queues[0][0].poll();
            }
            else if(bit==0 && !queues[0][1].isEmpty()){ // 짝수 날? 그럼 오른쪽 처리
                result+=queues[0][1].poll();
            }
 
            for(int i=1; i<n-width; i++){
                int parent = (i-1)/2;
                if(bit==1 && !queues[i][0].isEmpty()){ // 홀수 날? 그럼 왼쪽 처리
                    int poll = queues[i][0].poll();
                    if(i%2==1){
                        queues[parent][0].offer(poll); // 왼쪽 자식은 부모의 왼쪽에 넣거라
                    }
                    else{
                        queues[parent][1].offer(poll); // 오른쪽 자식..
                    }
                }
                else if(bit==0 && !queues[i][1].isEmpty()){ // 짝수 날? 그럼 오른쪽 처리
                    int poll = queues[i][1].poll();
                    if(i%2==1){
                        queues[parent][0].offer(poll); // 왼쪽 자식은 부모의 왼쪽에 넣거라
                    }
                    else{
                        queues[parent][1].offer(poll); // 오른쪽 자식..
                    }
                }
            }
 
            for(int i=n-width; i<n; i++){
                int parent = (i-1)/2;
                if(!queues[i][0].isEmpty()){ // 비어있지 않다면용
                    if(i%2==1){
                        queues[parent][0].offer(queues[i][0].poll()); // 왼쪽 자식은 부모의 왼쪽에 넣거라
                    }
                    else if(i%2==0){
                        queues[parent][1].offer(queues[i][0].poll()); // 오른쪽 자식..
                    }
                }
            }
            day++;
        }
        System.out.println(result);
    }
}
cs

 

 

- 말단 직원이 업무를 올릴 때 왼쪽 자식인지, 오른쪽 자식인지에 따라 부모의 왼쪽, 오른쪽 업무가 나뉘는데 이것을 구현 및 생각하는데 시간이 좀 걸린 문제

- 중간 직원 역시 자신의 조상에게 업무를 올릴 때의 메커니즘이 말단 직원과 같다는 사실을 간과했었음.