본문 바로가기

알고리즘/SW Expert Academy

[모의 SW 역량테스트] 2477. 차량 정비소

반응형

[모의 SW 역량테스트] 차량 정비소


1. 이해하기

  • N개의 접수 창구와 M개의 정비 창구가 있다.
  • 고객은 접수 창구에서 고장을 접수하고 끝나면 정비 창구로 간다.
  • 접수 창구 및 정비 창구의 담당자 업무 능력이 달라서 담당자 별 처리 시간이 다르다.
  • 고객은 도착하는 대로 1번부터 고객번호를 부여 받는다.
  • 접수 창구의 우선 순위
    • 여러 고객이 기다리고 있는 경우 고객번호가 낮은 순서대로 우선 접수한다.
    • 빈 창구가 여러 곳인 경우 접수 창구번호가 작은 곳으로 간다.
  • 정비 창구의 우선 순위
    • 먼저 기다리는 고객이 우선한다.
    • 두 명 이상의 고객들이 접수 창구에서 동시에 접수를 완료하고 정비 창구로 이동한 경우, 이용했던 접수 창구번호가 작은 고객이 우선한다.
    • 빈 창구가 여러 곳인 경우 정비 창구번호가 작은 곳으로 간다.
  • 지갑을 분실한 고객과 같은 접수 창구와 같은 정비 창구를 이용한 고객의 고객번호들을 찾아 그 합을 구하는 문제.
  • 시뮬레이션 문제.

2. 구현하기

  • 접수 창구와 정비 창구의 작동을 구현한다.

    • 접수 창구가 비어있다면 차례대로 고객을 넣어준다.
    • 접수 창구에서 일이 끝난 고객은 정비 창구로 바로 이동한다. 정비 창구가 꽉 차있으면 기다린다.
    • 가장 늦게 도착한 고객의 시간보다 지난 시간을 클 경우, 접수 창구와 정비 창구가 모두 비어있다면 작동을 멈춘다.
    void process_work() {
        memset(reception,0,sizeof(reception));
        memset(repair,0,sizeof(repair));
        queue<int> rep_wait;
        int time = 0;
        int index = 1;
        while(1) {
            for(int i = 1; i <= N; i++) {
                if(reception[i].time > 0) {
                    reception[i].time--;
                    if(reception[i].time == 0) {
                        rep_wait.push(reception[i].client_num);
                        reception[i].client_num = 0;
                    }
                }
            }
    
            while(index <= K and client[index].arr_time <= time) {
                bool flag = false;
                for(int i = 1; i <= N; i++) {
                    if(reception[i].time == 0) {
                        reception[i].time = rec_time[i];
                        reception[i].client_num = index;
                        client[index++].rec = i;
                        flag = true;
                        break;
                    }
                }
                if(!flag) break;
            }
    
            for(int i = 1; i <= M; i++) {
                if(repair[i].time > 0) {
                    repair[i].time--;
                }
            }
            while(!rep_wait.empty()) {
                bool flag = false;
                for(int i = 1; i <= M; i++) {
                    if(repair[i].time == 0) {
                        int now = rep_wait.front(); rep_wait.pop();
                        repair[i].time = rep_time[i];
                        client[now].rep = i;
                        flag = true;
                        break;
                    }
                }
                if(!flag) break;
            }
            time++;
            if(time > client[K].arr_time) {
                int cnt = 0;
                for(int i = 1; i <= N; i++) {
                    if(reception[i].time == 0) cnt++;
                }
                for(int i = 1; i <= M; i++) {
                    if(repair[i].time == 0) cnt++;
                }
                if(cnt == N+M) break;
            }
        }
    }
  • 고객들의 접수 창구 번호와 정비 창구 번호를 비교해 고객 번호들의 합을 구한다.

    int get_client_num() {
        int ret = -1;
        for(int i = 1; i <= K; i++) {
            if(client[i].rec == A and client[i].rep == B) {
                if(ret == -1) ret = 0;
                ret+=i;
            }
        }
        return ret;
    }

3. 전체 코드

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
struct INF {
    int client_num, time;
};
struct Client {
    int rec,rep,arr_time;
} client[1001];
INF reception[10], repair[10];
int rec_time[10], rep_time[10];
int N,M,K,A,B;

void process_work() {
    memset(reception,0,sizeof(reception));
    memset(repair,0,sizeof(repair));
    queue<int> rep_wait;
    int time = 0;
    int index = 1;
    while(1) {
        for(int i = 1; i <= N; i++) {
            if(reception[i].time > 0) {
                reception[i].time--;
                if(reception[i].time == 0) {
                    rep_wait.push(reception[i].client_num);
                    reception[i].client_num = 0;
                }
            }
        }

        while(index <= K and client[index].arr_time <= time) {
            bool flag = false;
            for(int i = 1; i <= N; i++) {
                if(reception[i].time == 0) {
                    reception[i].time = rec_time[i];
                    reception[i].client_num = index;
                    client[index++].rec = i;
                    flag = true;
                    break;
                }
            }
            if(!flag) break;
        }

        for(int i = 1; i <= M; i++) {
            if(repair[i].time > 0) {
                repair[i].time--;
            }
        }
        while(!rep_wait.empty()) {
            bool flag = false;
            for(int i = 1; i <= M; i++) {
                if(repair[i].time == 0) {
                    int now = rep_wait.front(); rep_wait.pop();
                    repair[i].time = rep_time[i];
                    client[now].rep = i;
                    flag = true;
                    break;
                }
            }
            if(!flag) break;
        }
        time++;
        if(time > client[K].arr_time) {
            int cnt = 0;
            for(int i = 1; i <= N; i++) {
                if(reception[i].time == 0) cnt++;
            }
            for(int i = 1; i <= M; i++) {
                if(repair[i].time == 0) cnt++;
            }
            if(cnt == N+M) break;
        }
    }
}

int get_client_num() {
    int ret = -1;
    for(int i = 1; i <= K; i++) {
        if(client[i].rec == A and client[i].rep == B) {
            if(ret == -1) ret = 0;
            ret+=i;
        }
    }
    return ret;
}

void input() {
    cin >> N >> M >> K >> A >> B;
    for(int i = 1; i <= N; i++) cin >> rec_time[i];
    for(int i = 1; i <= M; i++) cin >> rep_time[i];
    for(int i = 1; i <= K; i++) cin >> client[i].arr_time;
}

int main() {
    int T;
    cin >> T;
    for(int t = 1; t <= T; t++) {
        input();
        process_work();
        cout << '#' << t << ' ' << get_client_num() << '\n';
    }
    return 0;
}