코딩 테스트 공부
[백준 23309] 철도 공사 (자바스크립트)
개발새발개발자_
2025. 3. 6. 00:26
문제
연세대학교가 위치한 신촌역이 속한 2호선은 그림과 같이 개의 역이 원형으로 연결되어 있다. 각 역은 고유 번호가 할당돼 있으며 역들의 고유 번호는 서로 다르다. 그리고 특정 역의 다음 역은 시계 방향으로 인접한 역을 의미하고, 이전 역은 반시계 방향으로 인접한 역을 의미한다.
2호선은 지하철 노선들 중 유일한 흑자 노선이다. 때문에 2호선 공사 자금이 넉넉하기에 M번의 공사를 거치려고 한다. 각 공사는 다음 4가지 중 하나를 시행한다.
- 고유 번호 i를 가진 역의 다음 역의 고유 번호를 출력하고, 그 사이에 고유 번호 j인 역을 설립한다.
- 고유 번호 i를 가진 역의 이전 역의 고유 번호를 출력하고, 그 사이에 고유 번호 j인 역을 설립한다.
- 고유 번호 i를 가진 역의 다음 역을 폐쇄하고 그 역의 고유 번호를 출력한다.
- 고유 번호 i를 가진 역의 이전 역을 폐쇄하고 그 역의 고유 번호를 출력한다.
이 때, 이미 설립한 역은 다시 설립하지 않으며 폐쇄한 역은 다시 설립될 수 있다. 그리고 폐쇄 작업은 현재 설립된 역이 2 개 이상일 때만 들어온다.
2호선을 공사하는 프로그램을 만들어보자.
입력
첫 번째 줄에 공사를 시작하기 이전에 있는 역의 개수를 나타내는 양의 정수 N과 공사 횟수를 나타내는 양의 정수 M이 주어진다. (1 ≤ N ≤ , 1≤ M ≤ )
두 번째 줄에는 공사를 시작하기 이전에 있는 역의 고유 번호를 시계 방향 순서대로 주어진다. 같은 고유 번호를 가진 역은 주어지지 않는다.
이후 M개의 줄에 걸쳐서 공사에 대한 정보를 다음과 같이 주어진다.
- BN i j : 고유 번호 i를 가진 역의 다음 역의 고유 번호를 출력하고, 그 사이에 고유 번호 j인 역을 설립한다.
- BP i j : 고유 번호 i를 가진 역의 이전 역의 고유 번호를 출력하고, 그 사이에 고유 번호 j인 역을 설립한다.
- CN i : 고유 번호 i를 가진 역의 다음 역을 폐쇄하고 그 역의 고유 번호를 출력한다.
- CP i : 고유 번호 i를 가진 역의 이전 역을 폐쇄하고 그 역의 고유 번호를 출력한다.
입력으로 들어오는 모든 역의 고유 번호는 1 이상 이하의 양의 정수다. 폐쇄 작업은 현재 설립된 역이 2개 이상일 때만 들어오며, 이미 설립된 역은 또 설립될 수 없지만 폐쇄된 역은 다시 설립될 수 있다.
출력
각 공사에 대한 출력 값을 M개의 줄에 걸쳐서 출력한다.
#풀이과정
문제 자체는 원형 연결 리스트로 풀 수 있다.
진짜 문제는 시간 초과 난다는 것...
시간 초과를 어떻게 해결해야 할지 몰라서.. 일단 완성한 코드..
const input = require("fs")
.readFileSync(
process.platform === "linux" ? "/dev/stdin" : "./BOJ/BOJ_23309_input.txt"
)
.toString()
.trim()
.split("\n");
class Node {
constructor(id) {
this.id = id;
this.next = null;
this.prev = null;
}
}
class CircularLinkedList {
constructor() {
this.nodes = new Map();
this.head = null;
}
init(id) {
if (id.length === 0) return;
// 첫 번째 값을 헤드로 지정
let prevNode = new Node(id[0]);
this.head = prevNode;
this.nodes.set(id[0], prevNode);
const firstNode = prevNode;
// 원형 리스트 생성
for (let i = 1; i < id.length; i++) {
let newNode = new Node(id[i]);
prevNode.next = newNode;
newNode.prev = prevNode;
this.nodes.set(id[i], newNode);
prevNode = newNode;
}
// 마지막 노드와 첫 번째 노드 연결
prevNode.next = firstNode;
firstNode.prev = prevNode;
}
// BN i j : 고유 번호 i를 가진 역의 다음 역의 번호를 출력 후, 그 사이에 고유 번호 j의 역을 삽입
BN(i, j) {
const current = this.nodes.get(i);
const nextNode = current.next;
const output = nextNode.id;
const newNode = new Node(j);
// 새로운 노드를 current와 nextNode 사이에 삽입
current.next = newNode;
newNode.prev = current;
newNode.next = nextNode;
nextNode.prev = newNode;
// 새로운 역 추가
this.nodes.set(j, newNode);
return output;
}
// BP i j : 고유 번호 i를 가진 역의 이전 역의 번호를 출력 후, 그 사이에 고유 번호 j의 역을 삽입
BP(i, j) {
const current = this.nodes.get(i);
const prevNode = current.prev;
const output = prevNode.id;
const newNode = new Node(j);
// 새로운 노드를 prevNode와 current 사이에 삽입
prevNode.next = newNode;
newNode.prev = prevNode;
newNode.next = current;
current.prev = newNode;
// 새로운 역 추가
this.nodes.set(j, newNode);
return output;
}
// CN i : 고유 번호 i를 가진 역의 다음 역을 폐쇄(삭제)하고, 그 역의 번호를 출력
CN(i) {
const current = this.nodes.get(i);
const removeNode = current.next;
const output = removeNode.id;
const afterRemove = removeNode.next;
// current와 afterRemove를 연결하여 removeNode를 리스트에서 제외
current.next = afterRemove;
afterRemove.prev = current;
// 폐쇄된 역 제거
this.nodes.delete(removeNode.id);
return output;
}
// CP i : 고유 번호 i를 가진 역의 이전 역을 폐쇄(삭제)하고, 그 역의 번호를 출력
CP(i) {
const current = this.nodes.get(i);
const removeNode = current.prev;
const output = removeNode.id;
const beforeRemove = removeNode.prev;
// beforeRemove와 current을 연결하여 removeNode를 리스트에서 제외
current.prev = beforeRemove;
beforeRemove.next = current;
// 폐쇄된 역 제거
this.nodes.delete(removeNode.id);
return output;
}
}
const [N, M] = input[0].split(" ").map(Number);
const initialStations = input[1].split(" ").map(Number);
const list = new CircularLinkedList();
list.init(initialStations);
const outputLines = [];
for (let i = 2; i < 2 + M; i++) {
const parts = input[i].split(" ");
const command = parts[0];
if (command === "BN") {
const station = Number(parts[1]);
const newStation = Number(parts[2]);
const res = list.BN(station, newStation);
outputLines.push(res);
} else if (command === "BP") {
const station = Number(parts[1]);
const newStation = Number(parts[2]);
const res = list.BP(station, newStation);
outputLines.push(res);
} else if (command === "CN") {
const station = Number(parts[1]);
const res = list.CN(station);
outputLines.push(res);
} else if (command === "CP") {
const station = Number(parts[1]);
const res = list.CP(station);
outputLines.push(res);
}
}
console.log(outputLines.join("\n"));