11964 - Fruit Feast (Java)

박세건·2025λ…„ 2μ›” 12일
0
post-thumbnail

πŸ”— 문제 링크: λ°±μ€€ 11964번 - Hot Dogs?


πŸ“Œ 문제 μ„€λͺ…

  • λͺ©ν‘œ 점수 T κ°€ μ£Όμ–΄μ§€κ³ , 두 κ°€μ§€ 점수 νšλ“ 방법 A, Bκ°€ μ£Όμ–΄μ§„λ‹€.
  • ν•œ λ²ˆμ— A점 λ˜λŠ” B점을 얻을 수 있음.
  • μΆ”κ°€μ μœΌλ‘œ /2 연산을 ν•œ 번만 μˆ˜ν–‰ κ°€λŠ₯ (ν˜„μž¬ 점수λ₯Ό 절반으둜 μ€„μ΄λŠ” 것).
  • T μ΄ν•˜μ—μ„œ μ΅œλŒ€ 점수λ₯Ό κ΅¬ν•˜λŠ” 문제.

πŸ’‘ 풀이 방법: BFS 탐색 (졜적 ν•΄ 보μž₯)

πŸ”Ή 1️⃣ DP μ ‘κ·Ό μ‹œλ„ (μ‹€νŒ¨)

μ²˜μŒμ—λŠ” DP둜 해결을 μ‹œλ„ν–ˆμœΌλ‚˜, 졜적 λΆ€λΆ„ ꡬ쑰(Optimal Substructure) λ₯Ό λ§Œμ‘±ν•˜μ§€ μ•Šμ•„ μ‹€νŒ¨.

  • /2 연산이 λΉ„μ„ ν˜•μ μΈ λ³€ν™”λ₯Ό λ§Œλ“€λ©°, 이전 μƒνƒœμ˜ μ΅œμ ν•΄λ₯Ό μž¬μ‚¬μš©ν•  수 μ—†μŒ.
  • 즉, dp[i] = max(dp[i - A], dp[i - B], dp[i / 2]) 같은 점화식을 λ§Œλ“€ 수 μ—†μŒ.
  • βœ… κ·Έλž˜μ„œ BFSλ₯Ό μ‚¬μš©ν•˜μ—¬ 졜적 ν•΄λ₯Ό μ°ΎλŠ” λ°©μ‹μœΌλ‘œ μ „ν™˜.

πŸ”₯ BFSλ₯Ό ν™œμš©ν•œ 풀이

BFSλ₯Ό ν™œμš©ν•˜λ©΄, μ΅œμ†Œν•œμ˜ μ—°μ‚°μœΌλ‘œ μ΅œλŒ€ 점수λ₯Ό 찾을 수 있음.

πŸ”Ή BFS 탐색 κ³Όμ •

  1. Queue<int[]> λ₯Ό μ‚¬μš©ν•˜μ—¬ 탐색 (ν˜„μž¬ 점수, /2 μ—°μ‚° μ‚¬μš© μ—¬λΆ€).
  2. 맀번 A λ˜λŠ” Bλ₯Ό λ”ν•œ 값이 T μ΄ν•˜μΈμ§€ 확인 ν›„ 큐에 μΆ”κ°€.
  3. /2 연산을 아직 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ ν•œ 번만 μ‹€ν–‰ κ°€λŠ₯.
  4. μ΅œλŒ€ 점수(answer)λ₯Ό 계속 κ°±μ‹ ν•˜λ©° BFS 탐색 μ§„ν–‰.

πŸ“ μ½”λ“œ κ΅¬ν˜„

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    private static StringTokenizer st;
    private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    private static int T, A, B;
    private static boolean[][] visited; // [ν˜„μž¬ 점수][/2 μ—°μ‚° μ‚¬μš© μ—¬λΆ€]

    public static void main(String[] args) throws IOException {
        st = new StringTokenizer(br.readLine());
        T = Integer.parseInt(st.nextToken());
        A = Integer.parseInt(st.nextToken());
        B = Integer.parseInt(st.nextToken());

        visited = new boolean[T + 1][2]; // μ΅œλŒ€ TκΉŒμ§€ 탐색
        int answer = 0;

        Queue<int[]> queue = new ArrayDeque<>();
        queue.add(new int[]{0, 0}); // (ν˜„μž¬ 점수, /2 μ—°μ‚° μ‚¬μš© μ—¬λΆ€)

        while (!queue.isEmpty()) {
            int[] cur = queue.poll();
            int point = cur[0];
            int isDrink = cur[1];

            answer = Math.max(answer, point); // μ΅œλŒ€ 점수 κ°±μ‹ 
            if (answer == T) break; // μ΅œλŒ€ μ μˆ˜μ— λ„λ‹¬ν•˜λ©΄ μ’…λ£Œ

            // A 점수λ₯Ό μΆ”κ°€ν•  수 μžˆλŠ” 경우
            if (point + A <= T && !visited[point + A][isDrink]) {
                visited[point + A][isDrink] = true;
                queue.add(new int[]{point + A, isDrink});
            }

            // B 점수λ₯Ό μΆ”κ°€ν•  수 μžˆλŠ” 경우
            if (point + B <= T && !visited[point + B][isDrink]) {
                visited[point + B][isDrink] = true;
                queue.add(new int[]{point + B, isDrink});
            }

            // /2 연산을 아직 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ ν•œ 번만 μ‹€ν–‰ κ°€λŠ₯
            if (isDrink == 0 && !visited[point / 2][1]) {
                visited[point / 2][1] = true;
                queue.add(new int[]{point / 2, 1});
            }
        }

        System.out.println(answer);
    }
}

βœ… μ½”λ“œ μ΅œμ ν™” 및 κ°œμ„ 

πŸš€ 1️⃣ BFS 탐색 μ΅œμ ν™”

  • λΆˆν•„μš”ν•œ /2 μ—°μ‚° λ°©μ§€
    • /2 연산을 μ μš©ν•  λ•Œ, point / 2 == point이면 큐에 넣을 ν•„μš” μ—†μŒ. (0, 1, 2 λ“±)
  • visited λ°°μ—΄ ν™œμš© μ΅œμ ν™”
    • visited[point][isDrink]λ₯Ό μ‚¬μš©ν•˜μ—¬ 쀑볡 λ°©λ¬Έ λ°©μ§€.

πŸš€ 2️⃣ BFS vs DP 비ꡐ

λ°©λ²•μ‹œκ°„λ³΅μž‘λ„μ΅œμ ν•΄ 보μž₯μ„€λͺ…
DP🚫 λΆˆκ°€λŠ₯🚫 보μž₯ X/2 연산이 λΉ„μ„ ν˜•μ μ΄λΌ 점화식을 λ§Œλ“€ 수 μ—†μŒ
BFSβœ… O(T log T)βœ… μ΅œμ ν•΄ 보μž₯μ΅œλ‹¨ 경둜 탐색 λ°©μ‹μœΌλ‘œ μ •ν™•ν•œ μ •λ‹΅ λ„μΆœ κ°€λŠ₯

πŸ“Œ κ²°λ‘ 

❌ DP둜 ν’€ 수 μ—†λŠ” 이유

🚫 졜적 λΆ€λΆ„ ꡬ쑰 (Optimal Substructure)λ₯Ό λ§Œμ‘±ν•˜μ§€ μ•ŠμŒ
🚫 쀑볡 λΆ€λΆ„ 문제 (Overlapping Subproblems)λ₯Ό ν™œμš©ν•  수 μ—†μŒ
βœ… λ”°λΌμ„œ, BFS둜 ν•΄κ²°ν•΄μ•Ό 함.

βœ… BFS μ΅œμ ν™”

  • Queue<int[]>λ₯Ό ν™œμš©ν•œ μƒνƒœ 탐색
  • visited[][]을 μ‚¬μš©ν•˜μ—¬ 쀑볡 탐색 λ°©μ§€
  • μ΅œλŒ€ 점수λ₯Ό κ°±μ‹ ν•˜λ©° 탐색 μ§„ν–‰
profile
λ©‹μžˆλŠ” μ‚¬λžŒ - 일단 ν•˜μž

0개의 λŒ“κΈ€