백준 1700번 - 멀티탭 스케줄링

장근영·2024년 7월 25일
0

BOJ - 그리디

목록 보기
9/35

문제

백준 1700번 - 멀티탭 스케줄링


아이디어

  • 멀티탭에 플러그를 하나씩 꽂으면서 더 이상 멀티탭 구멍이 남지 않은 상태에서 새로운 플러그를 꽂아야 할 때는 곧 다시 사용할 플러그는 남기고, 최대한 나중에 다시 쓰이는 플러그를 제거하는 것이 유리하다.
  • 코드랑 주석 설명 참고

예상 시간 복잡도

  • 멀티탭 구멍 개수 : N
  • 전기용품 사용 횟수 : K
  • 예상 시간 복잡도 : O(K^2 x N)

코드 구현

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;

public class BJ_1700 {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int n = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());

        int[] used = new int[k];

        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < k; i++) {
            used[i] = Integer.parseInt(st.nextToken());
        }

        int count = 0; //플러그를 빼는 횟수

        HashSet<Integer> multiTap = new HashSet<>(); //멀티탭

        for (int i = 0; i < k; i++) {

            //멀티탭에 꽂혀 있지 않고, 멀티탭이 가득 찬 경우
            //멀티탭에 꽂혀있는 플러그 중 하나를 빼야 한다.
            if (!multiTap.contains(used[i]) && multiTap.size() >= n) {

                //멀티탭에 꽂혀있는 플러그 중 나중에 또 써야 할 플러그 목록(순서 중요)
                ArrayList<Integer> reuse = new ArrayList<>();

                //멀티탭에 꽂혀있는 플러그 중 나중에 쓰이지 않을 플러그 목록
                HashSet<Integer> remain = new HashSet<>(multiTap);

                //나중에 써야 할 전기 용품 목록 탐색
                for (int j = i; j < k; j++) {

                    //나중에 써야 할 플러그가 이미 멀티탭에 꽂혀 있다
                    if (multiTap.contains(used[j]) && !reuse.contains(used[j])) {

                        //나중에 또 써야 할 플러그 목록에 추가
                        reuse.add(used[j]);

                        //나중에 쓰이지 않을 플러그 목록만 남기기 위해 제거
                        remain.remove(used[j]);
                    }
                }

                //만약 나중에 또 써야 할 플러그 수가 멀티탭 구멍보다 많다면 가장 마지막에 쓰일 플러그를 제거한다.
                if (reuse.size() >= n) {
                    multiTap.remove(reuse.get(reuse.size() - 1));

                //그렇지 않다면 나중에 쓰이지 않을 플러그들 중 아무거나 빼도 상관없다.
                } else if (!remain.isEmpty()) {
                    multiTap.remove(remain.iterator().next());
                }

                count++;
            }

            multiTap.add(used[i]); //멀티탭에 플러그 꽂기
        }

        System.out.println(count);
    }
}

profile
오늘 할 일을 내일로 미루지 말자.

0개의 댓글