JLOG

[C++] 백준 1966 : 프린터 큐 본문

Algorithm/알고리즘 풀이

[C++] 백준 1966 : 프린터 큐

정정선선 2021. 6. 13. 14:05
 

1966번: 프린터 큐

여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에

www.acmicpc.net


문제

여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에 쌓여서 FIFO - First In First Out - 에 따라 인쇄가 되게 된다. 하지만 상근이는 새로운 프린터기 내부 소프트웨어를 개발하였는데, 이 프린터기는 다음과 같은 조건에 따라 인쇄를 하게 된다.

  1. 현재 Queue의 가장 앞에 있는 문서의 ‘중요도’를 확인한다.
  2. 나머지 문서들 중 현재 문서보다 중요도가 높은 문서가 하나라도 있다면, 이 문서를 인쇄하지 않고 Queue의 가장 뒤에 재배치 한다. 그렇지 않다면 바로 인쇄를 한다.

예를 들어 Queue에 4개의 문서(A B C D)가 있고, 중요도가 2 1 4 3 라면 C를 인쇄하고, 다음으로 D를 인쇄하고 A, B를 인쇄하게 된다.

여러분이 할 일은, 현재 Queue에 있는 문서의 수와 중요도가 주어졌을 때, 어떤 한 문서가 몇 번째로 인쇄되는지 알아내는 것이다. 예를 들어 위의 예에서 C문서는 1번째로, A문서는 3번째로 인쇄되게 된다.

입력

첫 줄에 테스트케이스의 수가 주어진다. 각 테스트케이스는 두 줄로 이루어져 있다.

테스트케이스의 첫 번째 줄에는 문서의 개수 N(1 ≤ N ≤ 100)과, 몇 번째로 인쇄되었는지 궁금한 문서가 현재 Queue에서 몇 번째에 놓여 있는지를 나타내는 정수 M(0 ≤ M < N)이 주어진다. 이때 맨 왼쪽은 0번째라고 하자. 두 번째 줄에는 N개 문서의 중요도가 차례대로 주어진다. 중요도는 1 이상 9 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.

출력

각 테스트 케이스에 대해 문서가 몇 번째로 인쇄되는지 출력한다.

 

 

 

코드

#include <iostream>
#include <algorithm>

/* 1966 프린터 큐 */


bool compare(int i, int j){ // 오름차순 정렬을 위한 compare
    return j < i;
}

int main(void) {
    int test_case;
    scanf("%d", &test_case);

    for (; test_case > 0; test_case--){
        int num_paper, idx;   // 문서수, 언제 print 되는지 알고 싶은 idx
        int importance[100];  // 중요도 (최대 길이인 100으로 선언)
        
        // 변수 입력 
        scanf("%d %d", &num_paper, &idx);        

        for (int idx=0; idx < num_paper; idx++){
            scanf("%d", &importance[idx]);
        }

        // 정렬하기 위한 배열 복사 & 오름차순 정렬
        int sorted_importance[100];
        std::copy(importance, importance + num_paper, sorted_importance);
        std::sort(sorted_importance, sorted_importance+num_paper, compare);


        // importance의 현재 idx를 나타내는 변수
        int i=0;

        // sidx는 sorted_importance의 idx로서 우선순위가 높은 순서대로 importance와 배열이 일치하는지 검사
        // 일치한다면 sidx++ 해주어 다음 순서의 우선순위를 체크
        for (int sidx=0; sidx < num_paper; sidx++){
            while (sorted_importance[sidx] != importance[i]){
                i = (i + 1) % num_paper;
            }
            
            if (i == idx){ // 현재 importance idx와 알기 원하는 idx가 일치하는 경우 지금까지 출력한 개수와 동일한 sidx를 print
                printf("%d\n", sidx+1);
                break;
            }
            importance[i] = -1;
        }
    }
   return 0;
}
 

 

문제에서는 조건에 맞지 않는 원소들을 뒤로 붙여 큐 형식으로 사용했다.

하지만, 배열을 복사하고 자리를 옮기기에는 시간이 많이 소요되기 때문에, 단순히 idx의 위치만 변경하여 검사했다.

조건에 맞지 않는 원소들을 뒤로 붙인 형식으로는 기존 순서가 변화되지 않기 때문에 가능했다.

 

원래 순간순간 최대 중요도를 계산해 중요도 배열과 비교하여 출력 유무를 판단하지만,

매번 최대 중요도를 계산하는 것은 높은 시간 복잡도가 일어나기 때문에, sort 함수를 이용해 오름차순으로 정리하여 정렬된 중요도 배열과 기존의 중요도 배열을 비교하였다.

 

이때 정렬된 중요도 배열의 값과 기존의 중요도 배열의 값이 일치하는 경우 다음 중요도 배열의 원소를 검사하기 위해 sidx를 +1 해주고,

기존의 중요도 배열을 -1로 수정해, 다음 loop를 돌 때 고려하지 않도록 처리했다.

 

이때 sort 함수의 (idx+1)는 출력된 횟수와 동일하므로, 현재의 중요도 배열 위치(i)와 알고 싶은 인덱스(idx)와 일치할 때 sidx를 프린트 후 break를 걸어주어 loop를 나오도록 하였다.

 

 

 

Comments