Baekjoon #19940

Baekjoon #19940

1개의 풀이 · Java

문제 원문 보기 ↗

SOLUTION INFO

Java · Main.java

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

public class Main {
    public static void main(String[] args) {
        FastReader rd = new FastReader();

        HashMap<Integer, int[]> m = new HashMap<>();
        Queue<int[]> q = new LinkedList<>();
        int a[] = new int[]{0, 0, 0, 0, 0};
        m.put(0, a);
        q.add(a);

        while (!q.isEmpty()) {
            int[] curr = q.poll();
            int sum = curr[0] * 60 + curr[1] * 10 + curr[2] * -10 + curr[3] - curr[4];

            // MINO
            if (check(m, sum - 1)) {
                m.put(sum - 1, new int[]{curr[0], curr[1], curr[2], curr[3], curr[4] + 1});
                q.add(m.get(sum - 1));
            }

            // ADDO
            if (check(m, sum + 1)) {
                m.put(sum + 1, new int[]{curr[0], curr[1], curr[2], curr[3] + 1, curr[4]});
                q.add(m.get(sum + 1));
            }

            // MINT
            if (check(m, sum - 10)) {
                m.put(sum - 10, new int[]{curr[0], curr[1], curr[2] + 1, curr[3], curr[4]});
                q.add(m.get(sum - 10));
            }

            // ADDT
            if (check(m, sum + 10)) {
                m.put(sum + 10, new int[]{curr[0], curr[1] + 1, curr[2], curr[3], curr[4]});
                q.add(m.get(sum + 10));
            }

            // ADDH
            if (check(m, sum + 60)) {
                m.put(sum + 60, new int[]{curr[0] + 1, curr[1], curr[2], curr[3], curr[4]});
                q.add(m.get(sum + 60));
            }
        }

        int T = rd.nextInt();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < T; i++) {
            int time = rd.nextInt();
            int ans[] = new int[]{0, 0, 0, 0, 0};
            int ret = time / 60;
            ans[0] = ret;
            int[] rem = m.get(time % 60);
            for (int j = 0; j < 5; j++) {
                ans[j] += rem[j];
                sb.append(ans[j]).append(" ");
            }
            sb.append("\n");
        }
        System.out.print(sb.toString());
    }

    private static boolean check(HashMap<Integer, int[]> m, int next) {
        return next >= 0 && next <= 60 && !m.containsKey(next);
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

SOLUTION DESCRIPTION

풀이 설명

1. BFS 응용 문제. 단순히 BFS로만 해결하려는 경우, `N` 의 최대 크기가 `1e7` 이기에 시간초과가 나오기 때문에, 다른 접근법을 신경써야 한다. 2. 주어진 시간의 변화를 주는 최대 크기는 `60` 이다. 즉 `0~59` 이하의 버튼의 최소 횟수를 미리 구하여, 테스트 케이스 `N` 에 대하여 `N/60` 과 `N%60` 을 결합하는 방법으로 `N` 에 대한 버튼의 최소 횟수를 구할 수 있다. 3. 버튼에는 시간을 감소시키는 경우가 존재한다. 가령 `48` 의 경우, `ADDH` 를 적용시킨 `1 0 1 0 2` 버튼의 최소 횟수가 된다. 따라서 실제 구해야하는 시간의 변화는 `0~59` 이지만, `ADDH` 를 적용시킨 경우를 포함하기 위해 다음 노드로 향하는 `BFS` 의 탐색 조건은 `0<=t<=60` 이 되어야 한다.