[JAVA] Softeer 소프티어 회의실 예약
2022. 12. 17.
반응형

https://softeer.ai/app/assessment/index.html?xid=214878&xsrfToken=EfNszJmSIdoz0PABTpQTN8rSKAjIpWZm&testType=practice

 

Candidate | Softeer Assessment UI

 

softeer.ai

 

1. 서론

 

난이도가 별 두 개인점 & 정답률이 높은 점으로 미루어보아 그렇게 어려운 문제는 아니다. 그런데 나는 엄청 헤맸다.... 왜 그랬을까?

 

 

반응형

 

 

2. 문제 풀이

 

나는 처음에 이 문제가 백준에 있는 회의실 배정의 이름만 다른 버전인 줄 알았다. 그런데 전혀 아니었다.

 

회의실 배정:

https://coding-log.tistory.com/4

 

[C++] 백준 1931 회의실배정 (+ JAVA 코드 추가)

www.acmicpc.net/problem/1931 1931번: 회의실배정 (1,4), (5,7), (8,11), (12,14) 를 이용할 수 있다. www.acmicpc.net 1. 서론 이 문제는 그리디 알고리즘으로 풀 수 있다. 그리디 알고리즘이란 매 순간 최적의 방법을

coding-log.tistory.com

 

회의실의 개수와 그 회의실의 예약된 시간이 주어진다.

 

예를 들어 avante라는 회의실이 있고

avante 9 11
avante 12 13

라고 한다면

 

9~11시, 12~13시에는 예약이 잡혀있는 것이고

11~12시 13~18시에는 회의실이 비어있는 것이다.

 

 

 

그래서 회의실 별로 회의실이 비어있는 시간과 그 개수를 출력하는 것이 문제이다.

참고로 내가 이 문제를 풀 때 썼던 테케를 첨부합니다.

(소프티어는 테케를 진짜 빈약하게 줘서 무조건 엣지케이스 테스트를 해야 한다.)

 

tc:

1 2
avante
avante 9 11
avante 12 13

 

답:
Room avante:
2 available:
11-12
13-18

 

나는 문제를 좀 복잡하게 풀었다. 소프티어 문제들이 다 그렇듯 엄청 쉬워 보이는데 하다 보면 조건들을 구현하기 위해서 코드가 조금 복잡해진다. (물론 똑똑한 사람들은 쉽게 풀겠지...)

 

나는 회의실 별로 시간을 체크하기 위해서 회의실 이름과 배열을 세트로 묶은 클래스를 선언했다. 배열에는 9~18시의 회의실 예약 정보가 적혀있다. 0은 비어있는 시간 1은 점유시간 2는 회의가 끝나는 시간으로 설정했다.

 

그리고 입력을 처리하기 위해서 이름, 시작 시간, 끝나는 시간이 한 세트로 묶인 클래스도 별도로 선언했다. 그리고 위의 배열과 아래의 배열을 회의실 이름 순으로 정렬해서 세트로 맞춰줬다.

 

그리고 반복문을 돌면서 회의실 별로 시작, 끝나는 시간을 넣어줬다. 그리고 이 배열을 돌면서 회의실이 비어있는 시작 시간은 0이거나 2이므로 1이 아닌 경우를 시작으로 설정하고 0이 아닌 숫자가 나오는 순간은 회의실이 사용 중인 것이므로 그 시간을 끝나는 시간으로 설정해서 문제를 해결했다.

 

 

 

3. 코드 설명

 

import java.util.*;
import java.io.*;


public class Main
{
    public static void main(String args[]) throws Exception
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        List<Room> room = new ArrayList<>(); //방별 시간
        for (int i = 0; i < n; i++) {
            String s = br.readLine();
            int[] a = new int[19]; //9~18시까지
            room.add(new Room(s, a));
        }

        Collections.sort(room); //방 이름 순으로 정렬

        List<Info> info = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine());
            String name = st.nextToken();
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            info.add(new Info(name, start, end));
        }

        Collections.sort(info); //방 이름, 작은 시간 순으로 정렬

        int idx = 0;
        for (int i = 0; i < m; i++) {
            if (idx == n) break;
            if (room.get(idx).name.equals(info.get(i).name)) {
                for (int j = info.get(i).start; j < info.get(i).end; j++)
                    room.get(idx).a[j] = 1;
                room.get(idx).a[info.get(i).end] = 2; //끝나는 시간이 경우
            }
            else {
                idx++;
                i--;
            }
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append("Room " + room.get(i).name + ":\n");
            int chk = sb.length(), start = -1, j = 9, cnt = 0; //chk로 삽입 위치 기억
            
            while(j <= 18) {
                if (start == -1 && room.get(i).a[j] != 1) {
                    start = j++; //0, 2인경우 시작지점으로 선택
                    continue;
                }
                if (start != -1 && room.get(i).a[j] != 0 || (j == 18 && room.get(i).a[j] == 0)) { //0이 아니라면 회의실 점유중, 그러나 마지막 값은 0인 경우에만 사용 가능하므로 처리
                    if (start < 10) //0보다 작은 경우 문제에서 앞에 0을 붙여줬기 때문에 처리
                        sb.append("0");
                    sb.append(start + "-");
                    if (j < 10)
                        sb.append("0");
                    sb.append(j + "\n");
                    cnt++; // 가능 시간 갯수
                    start = -1; //시작 시간 초기화
                }
                j++;
            }
            if (cnt == 0) {
                sb.insert(chk, "Not available\n"); //모두 사용 중인 경우
            }
            else {
                sb.insert(chk, cnt + " available:\n");
            }
            if (i != n - 1) //마지막에는 사용하지 않음
                sb.append("-----\n");
        }

        bw.write(sb.toString());
        bw.close(); br.close();
    }
}

class Room implements Comparable<Room>{ //방 이름과 그 사용 시간 저장
    String name;
    int[] a;

    public Room(String name, int[] a) {
        this.name = name;
        this.a = a.clone();
    }

    @Override
    public int compareTo(Room o) { //이름 순 정렬
        return this.name.compareTo(o.name); //오름차순
    }
}

class Info implements Comparable<Info>{ //방 이름과 시작, 끝 시간 적음
    String name;
    int start, end;

    public Info(String name, int start, int end) {
        this.name = name;
        this.start = start;
        this.end = end;
    }

    @Override
    public int compareTo(Info o) {
        if (o.name.equals(this.name)) {
            if (this.start == o.start) //시작 시간 순
                return this.end - o.end; //끝나는 시간 순
            return this.start - o.start;
        }
        else return this.name.compareTo(o.name); //이름 순
    }
}

 

주석 참고!!!

 

 

 

 

반응형
myoskin