Programing/백준, 프로그래머스(C++)

[C++][백준 2839] 설탕 배달

hye3193 2025. 1. 9. 15:35

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

 

제출 코드

#include <iostream>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int count = 0;
    int n, left = 0;
    cin >> n;

    while (1)
    {
        if (n % 5 == 0) break;
        n -= 3;
        count++;
        if (n < 0)
        {
            cout << -1;
            return 0;
        }
    }
    cout << (n / 5) + count;
}

그리디나 DP에 대해 잘 모르고 작성한 코드라 밑에 각 접근법 별로 정리해두겠다

 

1. 그리디 알고리즘

그리디 알고리즘이란 매 단계마다 최적으로 보이는 선택을 반복해 최종적으로 최적에 가까운 해답을 찾는 과정이라고 한다

 

위 문제에서는 5kg짜리 봉지만 사용해서 운반이 가능하면 가장 최적이다

1. 우선 5kg짜리 봉지만 사용해서 운반이 가능한지를 체크(n % 5 == 0)

2. 운반이 불가하다면 3kg짜리 봉지를 하나 추가하면(n에서 3을 빼 준다) 나머지는 5kg로 운반이 가능한지 체크

3. 2번을 반복해서 체크하다, 조건을 만족하지 못했는데 남은 설탕의 양이 0보다 작아진다면 -1 출력

 

2. DP(동적 프로그래밍)

주어진 문제를 나눠서 하위 문제로 해결하여 이를 이용해 큰 문제를 해결하는 방법이라고 한다

다이나믹 프로그래밍에는 Top-Down 방식과 Bottom-up 방식이 존재한다

1) Top-Down: n번째부터 시작해서 0까지 내려간 다음, 결과값을 재활용하는 방식

2) Bottom-Up: 0부터 시작해서 n까지 가면서 값을 재활용하는 방식

 

1. 크기 5001짜리 배열(문제에서 n의 최댓값이 5000이므로)을 생성

2. n이 3일 때와 5일 때 각각 1봉지씩만 운반하면 되므로 값을 넣어두기(dp[3] = dp[5] = 1)

3. for loop를 돌면서 i - 3이나 i - 5의 값이 0이 아니라면(존재한다면) 해당 값에 봉지 하나를 더한 값을 dp[i]에 저장해 준다

* 이때 i - 3값이 존재해서 dp[i] = dp[i - 3] + 1을 저장해두었더라도, i - 5의 값도 존재한다면(이 경우가 더 봉지를 최소 갯수 운반하면 되므로) dp[i] = dp[i - 5] + 1값으로 재지정해줄 필요가 있다

#include <iostream>
using namespace std;

int dp[5001];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    dp[3] = 1;
    dp[5] = 1;
    for (int i = 6; i <= n; i++)
    {
        if (dp[i - 3])
            dp[i] = dp[i - 3] + 1;
        if (dp[i - 5])
            dp[i] = dp[i - 5] + 1;
    }
    if (dp[n])
        cout << dp[n];
    else
        cout << -1;
}