코딩테스트 문제 풀이 (C++)

백준 7579 - 앱 (C++)

오의현 2024. 6. 25. 13:40

 

 

 

N개의 앱이 켜있다고 해보자.

 

각 앱은 m_1, m_2, m_3....m_n의 메모리를 사용하고 있으며, 각 앱을 비활성화하게 되면 각 c_1, c_2, c_3, c_4...c_n의 비용이 발생하게 된다.

 

M바이트를 확보하기 위해, 임의의 앱을 비활성화 했을 때 발생하는 비용의 최소값을 구하자.

 

문제 풀이

문제 자체는 간단한 배낭 문제이다. 다만, 일반적인 배낭 문제와는 다르게 최소값을 구하는 문제이기 때문에 떠올리는 것이나 구현하는 것이 다소 어려울 수도 있었을 것 같다.

 

배낭문제는 보통 개수와 수치(무게, 비용 등)을 이용해서 2차원 배열을 구성하게 된다. 위의 문제에서 개수, 메모리를 이용해서 2차원 배열을 구성하게 되면 최대 1000000000개의 원소를 가지는 배열을 만들어야 하므로 메모리 초과가 발생할 수 밖에 없다. 그러므로 2차원 배열은 (개수, 비용)을 이용해서 구성할 것이다.

 

그렇다면, 배열의 원소는 어떤 값을 저장해야 할까?

문제에서 구하는 것은 M바이트를 확보하기 위한 최소 비용이다.

 

반대로, N의 비용을 사용했을 때 최대한으로 확보할 수 있는 메모리를 구하면 어떨까?

문제에서 주어진 최대 비용은 10000이다. (100개의 앱 * 100의 비용)

 

그러므로, N의 비용을 사용했을 때 최대한으로 확보할 수 있는 메모리를 배열에 저장한 뒤 0 ~ 10000 까지의 비용 중 확보할 수 있는 메모리가 입력값보다 큰 비용을 구한 뒤, 그 값의 최소를 출력하면 되는 것이다.

 

배열의 원소를 갱신하는 것은 일반 배낭 문제와 동일하게 하면 된다.

 

풀이 코드

int NumApp = 0;
int TargetMem = 0;

std::cin >> NumApp >> TargetMem;

std::vector<int> AppMemories(NumApp + 1, 0);
std::vector<int> AppCosts(NumApp + 1, 0);

for (int i = 1; i <= NumApp; i++)
{
    std::cin >> AppMemories[i];
}

for (int i = 1; i <= NumApp; i++)
{
    std::cin >> AppCosts[i];
}

먼저, 입력을 모두 받아주자.

앱의 개수와 확보할 메모리를 입력받은 뒤, 각 앱의 메모리 사용량과 비활성화시 발생하는 비용을 모두 저장해주었다.

std::vector<std::vector<int>> DP(NumApp + 1, std::vector<int>(10001, 0));

다음으로 배낭 문제 해결에 사용할 DP 배열을 만들어주었다.

발생할 수 있는 최대 비용은 10000이므로, 배열의 size를 위와 같이 만들어주었다.

for (int i = 1; i <= NumApp; i++)
{
    for (int j = 0; j <= 10000; j++)
    {
        if (j >= AppCosts[i])
        {
            DP[i][j] = std::max(DP[i - 1][j], DP[i - 1][j - AppCosts[i]] + AppMemories[i]);
        }
        else
        {
            DP[i][j] = DP[i - 1][j];
        }
    }
}

일반적인 배낭문제와 동일하게 반복문을 돌려주면 된다.

각 원소의 값은 i개의 앱을 비활성화하여 j의 비용이 발생했을 때 확보할 수 있는 최대 메모리양이다.

int Answer = 0;

for (int i = 0; i <= 10000; i++)
{
    if (DP[NumApp][i] >= TargetMem)
    {
        Answer = i;
        break;
    }
}

이후, i를 0부터 10000까지 반복문을 돌며 TargetMem을 확보할 수 있는 최소 비용을 구해주면 된다.

std::cout << Answer;

답을 출력해주면 된다.

 

 

코드 전문

더보기
#include <iostream>
#include <vector>
#include <algorithm>

void Init()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
}

int main()
{
    Init();

    int NumApp = 0;
    int TargetMem = 0;
    
    std::cin >> NumApp >> TargetMem;

    std::vector<int> AppMemories(NumApp + 1, 0);
    std::vector<int> AppCosts(NumApp + 1, 0);

    for (int i = 1; i <= NumApp; i++)
    {
        std::cin >> AppMemories[i];
    }

    for (int i = 1; i <= NumApp; i++)
    {
        std::cin >> AppCosts[i];
    }

    std::vector<std::vector<int>> DP(NumApp + 1, std::vector<int>(10001, 0));

    for (int i = 1; i <= NumApp; i++)
    {
        for (int j = 0; j <= 10000; j++)
        {
            if (j >= AppCosts[i])
            {
                DP[i][j] = std::max(DP[i - 1][j], DP[i - 1][j - AppCosts[i]] + AppMemories[i]);
            }
            else
            {
                DP[i][j] = DP[i - 1][j];
            }
        }
    }

    int Answer = 0;

    for (int i = 0; i <= 10000; i++)
    {
        if (DP[NumApp][i] >= TargetMem)
        {
            Answer = i;
            break;
        }
    }

    std::cout << Answer;

    return 0;
}