SWEA 2477 차량 정비소 - JAVA 📌
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV6c6bgaIuoDFAXy
풀이 기간으로는 이틀 좀 안걸렸어요.. 코응애한테는 너무 버거운 문제였다.
요새 모의 SW 역량테스트를 조금씩 건드려 보고 있는데,
마치 헬스로 따지면 벤치프레스 뽑지도 못하는 100kg을 뽑으려고 안간힘 쓰는데 절대 뽑을 수 없는 그런 느낌?
다시 기본기부터 천천히..
점진적 과부하 식으로 마음 급하게 먹지 않고 기본기부터 천천히 다져야 겠다는 생각이 들었다!
문제 풀이
접근 💡
지문에서 요구하는 것은 고객이 어느 창구에 머물렀냐는 것이다.
고객의 정보를 가지는 클래스를 하나 선언하자.
static class Person {
int customerNumber; //고객의 번호
int useReceptionNumber; //고객이 사용한 접수창구 번호
int useRepairNumber; //고객이 사용한 정비창구 번호
int stayTimeReception;// 고객이 접수창구에 머문 시간
int stayTimeRepair; // 고객이 정비창구에 머문 시간
public Person(int customerNumber, int useReceptionNumber, int useRepairNumber, int stayTimeReception, int stayTimeRepair) {
this.customerNumber = customerNumber;
this.useReceptionNumber = useReceptionNumber;
this.useRepairNumber = useRepairNumber;
this.stayTimeReception = stayTimeReception;
this.stayTimeRepair = stayTimeRepair;
}
}
문제를 푸는데 사용한 자료구조는 큐와 배열을 사용했다. 처음에는 고객이 도착한 순서대로 창구에 들어가야 된다는 생각에 우선순위 큐를 사용해야 하나 생각 했는데, 입력으로 주어지는 고객 도착 시간이 순서대로 주어지기 때문에 큐로 사용 했다.
그리고 접수창구와 정비창구로 사용할 배열을 사용했다.
while 문안에서 현재 시간마다
1. 도착 순서대로 접수창구 대기열에 넣기 ( 고객 번호 기록 )
2. 접수창구가 비어있으면 접수창구 대기열에서 접수창구로 이동 ( 고객이 이용한 접수창구 번호 기록)
3. 접수창구에서 고객이 머문 시간++
4. 접수창구 처리 시간이 끝나면 정비창구 대기열로 이동
5. 정비창구가 비어있으면 정비창구로 이동 (고객이 이용한 정비창구 번호 기록)
6, 정비창구에서 고객이 머문 시간++
7. 정비창구 처리 시간이 끝나면 정비가 끝난 고객의 카운트를 ++ 해줌.
끝난 고객이 머문 창구를 비교하여 맞다면 고객 번호를 ans에 누산 해주었다.
종료 조건으로는 고객의 수와 정비가 끝난 고객의 카운트가 같아질 때 종료를 해주었다.
코드 💡
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Solution {
static class Person {
int customerNumber;
int useReceptionNumber;
int useRepairNumber;
int stayTimeReception;
int stayTimeRepair;
public Person(int customerNumber, int useReceptionNumber, int useRepairNumber, int stayTimeReception, int stayTimeRepair) {
this.customerNumber = customerNumber;
this.useReceptionNumber = useReceptionNumber;
this.useRepairNumber = useRepairNumber;
this.stayTimeReception = stayTimeReception;
this.stayTimeRepair = stayTimeRepair;
}
}
private static int T, N, M, K, A, B;
private static int[] receptionTime, repairTime, customer;
private static Person[] reception;
private static Person[] repair;
private static Queue<Person> waitingReception;
private static Queue<Person> waitingRepair;
private static int ans;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
T = Integer.parseInt(br.readLine());
for (int tc = 1; tc <= T; tc++) {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
A = Integer.parseInt(st.nextToken());
B = Integer.parseInt(st.nextToken());
reception = new Person[N + 1]; // 실제 고객이 들어갈 접수창구
repair = new Person[M + 1]; // 실제 고객이 들어갈 정비창구
waitingReception = new LinkedList<>(); // 접수대기열
waitingRepair = new LinkedList<>();// 정비대기열
ans = 0;
// 창구번호를 표현할 배열, 고객들이 몇초에 도착하는지 표현할 배열
receptionTime = new int[N + 1];
st = new StringTokenizer(br.readLine());
for (int i = 1; i <= N; i++) {
receptionTime[i] = Integer.parseInt(st.nextToken());
}
repairTime = new int[M + 1];
st = new StringTokenizer(br.readLine());
for (int i = 1; i <= M; i++) {
repairTime[i] = Integer.parseInt(st.nextToken());
}
customer = new int[K + 1];
st = new StringTokenizer(br.readLine());
for (int i = 1; i <= K; i++) {
customer[i] = Integer.parseInt(st.nextToken());
}
int time = 0;
int completeCustomer = 0;
while (true) {
//모든 고객 처리 완료시 끝 종료
if (completeCustomer == K) {
break;
}
//도착한 시간이 되면 접수창구 대기열로!
for (int i = 1; i <= K; i++) {
if (customer[i] == time) {
waitingReception.offer(new Person(i, -1, -1, 0, 0));
}
}
//접수 창구가 비어있다면 접수창구 대기열에서 순서대로 접수창구로 이동
for (int i = 1; i <= N; i++) {
if (reception[i] == null && !waitingReception.isEmpty()) {
reception[i] = waitingReception.poll();
reception[i].useReceptionNumber = i; //번호기록
}
}
//접수 창구 머문 시간 기록
for (int i = 1; i <= N; i++) {
if (reception[i] != null) {
reception[i].stayTimeReception++;
}
}
//접수창구에서 처리가 완료 되었다! 정비창구 대기열로 가야함
for (int i = 1; i <= N; i++) {
if (reception[i] != null && reception[i].stayTimeReception == receptionTime[i]) {
waitingRepair.offer(reception[i]);
reception[i] = null;
}
}
//정비창구가 비어있다면 정비창구로 이동!
for (int i = 1; i <= M; i++) {
if (repair[i] == null && !waitingRepair.isEmpty()) {
repair[i] = waitingRepair.poll();
repair[i].useRepairNumber = i;
}
}
//정비창구 머문 시간 기록
for (int i = 1; i <= M; i++) {
if (repair[i] != null) {
repair[i].stayTimeRepair++;
}
}
//머문시간 끝나면 빠져 나간다.
for (int i = 1; i <= M; i++) {
if (repair[i] != null && repair[i].stayTimeRepair == repairTime[i]) {
completeCustomer++;
if (repair[i].useReceptionNumber == A && repair[i].useRepairNumber == B) {
ans += repair[i].customerNumber;
}
repair[i] = null;
}
}
time++;
}
if (ans == 0) {
ans = -1;
}
System.out.println("#" + tc + " " + ans);
}
}
}
문제를 풀어보며 많이 배워간 점은
시뮬레이션 문제를 풀 때 사용해야 할 적절한 자료구조를 떠올리는 것과
그림을 그려가며 설계를 완벽히 했을 때 코드에 손을 대야 더 효율적이라는 걸 배웠다.
그리고 코드를 작성할 때 어느 범위에서 시뮬레이션을 진행해야 하는지에 대해서도 많이 배웠다.
아직 부족하지만 여러 문제 많이 풀어보고 성장해야겠다!
'Algorithm' 카테고리의 다른 글
[TIP💡] 인텔리제이(Intellij)로 코딩테스트 환경 구성하기 (입출력을 txt로?) (0) | 2024.10.02 |
---|---|
[백준] 13418 학교 탐방하기 - JAVA (0) | 2024.09.22 |
[알고리즘] 비트 마스킹으로 '부분 집합' 구해보기 - JAVA (0) | 2024.08.24 |
[백준] 17471 게리 맨더링 - JAVA (0) | 2024.08.10 |
[백준] 14502 연구소 - JAVA (0) | 2024.08.01 |