본문 바로가기
Baekjoon/[3] DP

[백준] 2839번 설탕 배달 JAVA (자바) 풀이

by Poorm 푸름 2023. 9. 22.

문제 2839번 

 :  설탕 N킬로그램 배달해야 한다
    설탕은 봉지에 담겨져 있다 ( 3킬로그램 봉지 or 5킬로그램 봉지 )
    봉지의 최소 개수를 구해라

 

[입력]


 :  첫 줄에 N

 

 

[출력]


 :  봉지의 최소 개수 출력

    ( 정확하게 N킬로그램 만들 수 없다면 -1 출력 )



[설명]

 

DP 알고리즘

: 이미 계산된 결과는 별도의 메모리 영역에 저장하여 다시 계산하지 않음으로서 수행 시간 단축시키는 방법

  DP 구현 방법은 일반적으로 Top-down(하향식)과 Bottom-up(상향식)으로 구성된다

 

1) Top-down(하향식)


     하위 문제를 재귀적으로 호출하여 해결함으로서 상위 문제를 해결하는 방식
     이 때 해결해놓은 하위 문제를 저장해 놓기 위해 Memoization사용

 

public class Topdown {
	static int[] dp;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		dp  = new int[n+1];
		System.out.println(fibo(n));
		
	}
	
    // Top-down
	static int fibo(int x) {
		if( x ==1 || x==2) return 1;
		if(dp[x] != 0) return dp[x];
		dp[x] = fibo(x-1) + fibo(x-2);
		return dp[x];
	}
}

 

2) Bottom-up(상향식)

 

    하위에서부터 문제를 먼저 해결하고 얻어진 값들을 이용해서 상위 문제를 해결해나가는 방식

    반복문을 사용해서 구현하고 문제의 결과 값을 저장하는 리스트는 DP 테이블이라 부른다

    

public class Bottomup {

	static int[] dp;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		dp  = new int[n+1];
		
		System.out.println(fibo(n));
	}
	
    // Bottom-up
	static int fibo(int x) {
		dp[1] =1;
		dp[2] =1;
		for(int i=3; i<x+1; i++) {
			dp[i] = dp[i-1] + dp[i-2];
		}
		return dp[x];
	}

 

 

 

 [코드]

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int dp[] = new int[N + 1];
        int INF = Integer.MAX_VALUE;

        Arrays.fill(dp, INF);

        if (N >= 3) dp[3] = 1;
        if (N >= 5) dp[5] = 1;

        for (int i = 6; i <= N; i++) {
            if (dp[i - 3] != INF || dp[i - 5] != INF) {  // 유효한 값을 가지고 있을 때만 갱신
                dp[i] = Math.min(dp[i - 3], dp[i - 5]) + 1;
            }
        }

        System.out.println(dp[N] == INF ? -1 : dp[N]);
    }
}

 

 

 [해설]
     

 :  int N = Integer.parseInt(br.readLine());  첫째줄 입력 킬로그램

 

 :  int[] dp = new int[N + 1];  dp 설정 

    int INF = Integer.MAX_VALUE;  출력할 수 없는 킬로그램은 INF로 초기화

 

 :  Arrays.fill(dp, INF);  dp에 INF로 초기화
        
 :  if (N >= 3)  dp[3] = 1;  dp[3] = 3키로짜리 봉지 초기화
    if (N >= 5)  dp[5] = 1;  dp[5] = 5키로짜리 봉지 초기화

 

 :  for (int i = 6; i <= N; i++) {  5까지 값은 위에서 초기화 했으니까 6부터 시작
            if (dp[i - 3] != INF || dp[i - 5] != INF) {  하나라도 유효할 경우만 갱신
                dp[i] = Math.min(dp[i - 3], dp[i - 5]) + 1;  최소값 구하고 바로 1 count
            }
    }

    


 :  System.out.println(dp[n]==INF?-1:dp[n]);  INF면 -1로 출력하고 아니면 dp[n] 바로 출력

 

 

 

 

이제 풀어보러 갈께요 :)

 

 

 

* 독학으로 익히는 코딩이라 틀린 것이 있을 수 있습니다. 오류가 있다면 댓글을 통해 알려주세요. 감사합니다. *