본문 바로가기
PS/BOJ

[자바] 백준 1263 - 시간 관리 (java)

by Nahwasa 2023. 7. 20.

문제 : boj1263

 

 

필요 알고리즘

  • 그리디
    • 잘 생각해보면 어! 이렇게 하면 되지 않나? 싶은 룰이 있다. 

※ 제 코드에서 왜 main 함수에 로직을 직접 작성하지 않았는지, 왜 Scanner를 쓰지 않고 BufferedReader를 사용했는지 등에 대해서는 '자바로 백준 풀 때의 팁 및 주의점' 글을 참고해주세요. 백준을 자바로 풀어보려고 시작하시는 분이나, 백준에서 자바로 풀 때의 팁을 원하시는 분들도 보시는걸 추천드립니다.

 

 

풀이

  이 문제에서 물어보는건 모든 일을 끝낼 수 있는 가장 늦은 시간이다. 근데 좀 바꿔서 생각해보자. 애초에 모든 일을 끝낼 수 있나 없나를 어떻게 판단할 수 있을까?

 

  중요한건 S값이다. 언제 시작하는진 상관없고, 아무튼 N개의 일들에 대해 각 S값 이내로만 끝낼 수 있으면 모든 일이 가능한거다. 즉, 각각 (T,S)가 (2,7), (1,7), (3,7)인 3가지 일이 있다고 해보자. 어차피 S=7까지 셋 다 끝내야 한다. 어떤걸 먼저 하는지가 중요할까? 뭔가 S-T에 따라 해야할 것 같이 생겼지만, 어차피 1차원의 시간 내에 각각을 배치해야되고, S 이내로만 끝내면 되므로 S-T는 의미가 없다. 아래 그림처럼 T가 1인걸 먼저하든, 3인걸 먼저하든 상관 없다는 얘기다. 또 언제 하든 상관없다. 아무튼 S=7 이내로 끝내면 가능한거다.

 

  그럼 이제 가능한지 안한지는 생각해봤으니, 모든 일을 끝낼 수 있는 가장 늦은 시간은 어떻게 구할까? 간단하다. 최대한 빈 공간 없게 우측으로 붙여버리면 된다.

 

  그럼 이제 S가 다른 경우를 생각해보자. (T,S)가 (1,7), (2,5), (3,4) 이다. 이 경우엔 어떻게 배치해야할까? 전재조건은 최대한 우측으로 땡겨야 한다는 점이다. 그렇다면, S가 큰 것 부터 배치하는 것이 무조건 빈 공간을 최소화할 수 있다. 우선 S=7인걸 S=7에 둔다. 그리고 S=5인걸 S=5에 둔다. S=4인건 S=5인거가 T=2 이므로, S=4인 부분까지 사용하므로 거기에 못둔다. 그럼 그냥 빈 공간중 S=4 미만인 가장 큰 곳에 두면 된다! 빈 공간이 T만큼 안된다면? 그냥 -1 출력하고 종료하면 된다.

 

즉,

1. S가 동일하다면 뭘 먼저 두는진 상관없고 아무튼 최대한 우측으로 땡겨서 빈 공간에 둔다.

2. S가 다르다면 S가 큰 것 부터 최대한 우측에 배치하고 남는 공간에 그보다 S가 작은걸 두면 된다.

 

Arrays.sort(arr);	// S 내림차순 정렬

int pt = 1000000;
for (ToDo cur : arr) {
    pt = Math.min(pt, cur.s)-cur.t;	// Math.min(pt, cur.s)는 빈공간 중 S이하인 가장 큰 값이다.
    if (pt < 0) {	// 빈 공간이 없었다면 -1 출력하고 종료한다.
        System.out.println(-1);
        return;
    }
}

System.out.println(pt);

 

 

코드 : github

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in), 1<<16);

    public static void main(String[] args) throws Exception {
        new Main().solution();
    }

    private void solution() throws Exception {
        int n = Integer.parseInt(br.readLine());

        ToDo[] arr = new ToDo[n];
        while (n-->0) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int t = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());

            arr[n] = new ToDo(t, s);
        }

        Arrays.sort(arr);

        int pt = 1000000;
        for (ToDo cur : arr) {
            pt = Math.min(pt, cur.s)-cur.t;
            if (pt < 0) {
                System.out.println(-1);
                return;
            }
        }

        System.out.println(pt);
    }
}

class ToDo implements Comparable<ToDo> {
    int t, s;

    public ToDo(int t, int s) {
        this.t = t;
        this.s = s;
    }

    @Override
    public int compareTo(final ToDo o) {
        return o.s-s;
    }
}

 

댓글