여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에 쌓여서 FIFO - First In First Out - 에 따라 인쇄가 되게 된다. 하지만 상근이는 새로운 프린터기 내부 소프트웨어를 개발하였는데, 이 프린터기는 다음과 같은 조건에 따라 인쇄를 하게 된다.
예를 들어 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 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.
각 테스트 케이스에 대해 문서가 몇 번째로 인쇄되는지 출력한다.
3
1 0
5
4 2
1 2 3 4
6 0
1 1 9 1 1 1
1
2
5
const fs = require('fs');
let [cases, ...input] = fs.readFileSync(0, 'utf-8').toString().trim().split('\n');
cases = Number(cases);
let N = 0;
let M = 0;
let documents = [];
class Queue {
constructor() {
(this.storage = {}), (this.front = 0), (this.rear = 0);
}
size() {
if (this.storage[this.rear] === undefined) return 0;
else return this.rear - this.front + 1;
}
enqueue(value) {
if (this.size() === 0) this.storage[0] = value;
else {
this.rear += 1;
this.storage[this.rear] = value;
}
}
dequeue() {
let value = this.storage[this.front];
delete this.storage[this.front];
if (this.front === this.rear) {
this.front = 0;
this.rear = 0;
} else this.front += 1;
return value;
}
current() {
return this.storage[this.front];
}
}
let line = 0;
for (let i = 0; i < cases; i++) {
let queue = new Queue();
N = Number(input[line].trim().split(' ')[0]);
M = Number(input[line++].trim().split(' ')[1]);
documents = input[line++].trim().split(' ').map(Number);
for (let j = 0; j < documents.length; j++) {
if (j === M) queue.enqueue(documents[j] + 10);
else queue.enqueue(documents[j]);
}
documents.sort((a, b) => b - a);
let index = 0;
while (true) {
if (documents.length === index) break;
if (queue.current() === documents[index]) {
queue.dequeue();
index++;
} else if (queue.current() % 10 === documents[index]) {
queue.dequeue();
index++;
break;
} else {
queue.enqueue(queue.dequeue());
}
}
console.log(index);
}
큐를 이용해서 쉽게 삭제를 하는 것까지 구현하긴 했으나... 삭제되는 문서가 어떤 것인지를 알아내기가 너무 어려웠다. 중요도가 모두 다르면 괜찮지만, 마지막 예제처럼 중요도 1이 5개나 있을 경우, 어느 것이 먼저 삭제될지는 모르기 때문이다. 처음에는 해당 문서의 key값을 저장해둘까 했는데.. 계속 맨 뒤로 가면서 key값이 자주 바뀌기 때문에 좋지 않은 방법 같아서 고민을 많이했다. 다행히 10을 더해주자는 좋은 방법이 떠올랐다. (오랜만에 알고리즘 잘 짠 것 같음)
우선순위 큐를 이용하면 쉽다는데 오늘은 큐만 공부했기 때문에 우선순위 큐는 며칠 뒤에 공부해서 다른 문제에서 구현해보도록 하겠다.