Algorithm/BOJ

[백준] 2839 설탕배달

메린지 2024. 4. 8. 21:23

실4

1. 문제

https://www.acmicpc.net/problem/2839

 

2839번: 설탕 배달

상근이는 요즘 설탕공장에서 설탕을 배달하고 있다. 상근이는 지금 사탕가게에 설탕을 정확하게 N킬로그램을 배달해야 한다. 설탕공장에서 만드는 설탕은 봉지에 담겨져 있다. 봉지는 3킬로그

www.acmicpc.net

 

2. 풀이

 

실버 수준의 그리디/DP 문제이다.

 

예전에 그리디하게는 풀었었는데, DP로도 풀고 싶어서 다시 풀었다!!

 

1) Greedy 방법

 

1-1) 우선 그리디하게 풀어야하니까, 현재상황에서 가장 최선이도록 욕심을 부려야한다 == 5키로를 최대한 들자 !
1-2) 따라서 간단하다. 현재 주어진 숫자에 5로 나눠서 나눠지면 바로, 아니면 3씩 줄여가면서 5의 배수를 찾아가는지 해보면된다. 마지막까지 없으면 -1 출력.

 

## code ##

import sys

N = int(sys.stdin.readline())
cnt = 0
while True:
    if N < 3 and N > 0:
        print(-1)
        break
    if N % 5 == 0:
        cnt += N // 5
        print(cnt)
        break
    else:
        N -= 3
        cnt += 1

 

2) Dynamic Programming - Top Down 방식, 태뷸레이션

 

dp 라는 저장용 리스트를 선언해서 밑부터 채워가면서 올라가서 정답에 도달하는 방식이다.

2-1) 처음엔 모든 리스트에 -1로 초기화를 하고, dp[3], dp[5] = 1로 설정한다.
2-2) 점화식을 세워야하는데, 생각을 해보자.
설탕 배달에는 3과 5키로만 쓰인다. 그 즉슨, 이전 무게에 3을 올리거나 5를 올리면서 현재 무게에 맞는 개수를 찾는건데, 그중에서도 최소를 찾는다. 그러면 min( dp [ n - 3 ], dp [ n - 5 ] ) 이고, 여기에 +1을 해서 현재 무게까지 맞추도록 하면 되는거다 !!
따라서 점화식은 dp[n] = min(dp[n-3], dp[n-5]) + 1 !!!!
2-3) 근데 이게 3, 5 이후에도 -1인 친구들이 있는데, 7, 8같은 애들이고 또  6은 3 두개로 되니까 애매하다. 그래서 만약 7, 8 이런 숫자들 잘못 걸리면 -1로 min 계산 해야해서 중간에 꼬여버린다.
그래서 코드 상에서 만약 n-3 , n-5 값들이 -1인 경우 가지고도 조작을 해줘야 정답이 나온다.

 

## code ##

import sys

N = int(sys.stdin.readline())

def dynamic(i):
    dp = [-1] * (i+5)
    dp[3]=dp[5]=1

    for n in range(6, i+1):
        A = dp[n-3]
        B = dp[n-5]

        if A < 0 and B < 0:
            dp[n] = -1
        elif B<0:
            dp[n] = 1 + A
        elif A<0:
            dp[n] = 1 + B
        else:
            dp[n] = 1 + min(A, B)
    return dp[i]

print(dynamic(N))