BOJ

[c/c++] 백준 7579

qefoi 2022. 12. 2. 23:35

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

 

7579번: 앱

입력은 3줄로 이루어져 있다. 첫 줄에는 정수 N과 M이 공백문자로 구분되어 주어지며, 둘째 줄과 셋째 줄에는 각각 N개의 정수가 공백문자로 구분되어 주어진다. 둘째 줄의 N개의 정수는 현재 활

www.acmicpc.net

 

접근 방식

냅색(knapsack) 알고리즘을 이용하여 접근했다. 일반적인 알고리즘에서의 w(무게)를 메모리, v(가치)를 비용으로 대응했다. 하지만 이렇게 냅색 알고리즘을 이용하게 되면 배열의 크기가 100*10,000,000이 훨씬 넘어가게 되므로 제한 조건을 어기게 된다.

 

풀이 방법

배열의 크기가 문제가 되므로 배열의 크기를 줄일 방법을 생각했다. 위에서 생각했던 방법은 dp[i][j] : i번째까지 앱을 살펴봤을 때, 메모리가 j일 때 가치의 최댓값인데, 반대로 j를 가치로 하고 배열에 메모리를 저장하게 된다면 배열의 크기가 크다는 문제를 해결할 수 있다. 그래서 dp[i][j] : i번째까지 앱을 살펴봤을 때, 가치가 j이하를 만족하는 메모리 합의 최댓값이라고 정의했다.

코드

#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int n,m;
    int cost_sum=0; //cost들의 총합
    int min_cost=987654321;
    int memory[101]={0};
    int cost[101]={0};
    int dp[101][10001]={0}; //dp[i][j] : i번째까지 앱을 살펴봤을 때, 가치가 j이하를 만족하는 메모리 합의 최댓값
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>memory[i];
    for(int i=1;i<=n;i++){
        cin>>cost[i];
        cost_sum+=cost[i];
    }
    
    for(int i=1;i<=n;i++){
        for(int j=0;j<=cost_sum;j++){
            if(j-cost[i]>=0){
                dp[i][j]=max(dp[i][j],dp[i-1][j-cost[i]]+memory[i]);
            }
            dp[i][j]=max(dp[i][j],dp[i-1][j]);
            if(dp[i][j]>=m){
                if(min_cost>j) min_cost=j;
            }
        }
    }
    cout<<min_cost;
    return 0;
}

dp를 다 구하고 값이 m이상인 값들 중에서 j가 최소인 값을 찾으면 된다.