View

[백준] 7579 - 앱

sm_amoled 2021. 12. 26. 13:07
300x250

문제링크

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

문제

우리는 스마트폰을 사용하면서 여러 가지 앱(App)을 실행하게 된다. 대개의 경우 화면에 보이는 ‘실행 중’인 앱은 하나뿐이지만 보이지 않는 상태로 많은 앱이 '활성화'되어 있다. 앱들이 활성화 되어 있다는 것은 화면에 보이지 않더라도 메인 메모리에 직전의 상태가 기록되어 있는 것을 말한다. 현재 실행 중이 아니더라도 이렇게 메모리에 남겨두는 이유는 사용자가 이전에 실행하던 앱을 다시 불러올 때에 직전의 상태를 메인 메모리로부터 읽어 들여 실행 준비를 빠르게 마치기 위해서이다.

하지만 스마트폰의 메모리는 제한적이기 때문에 한번이라도 실행했던 모든 앱을 활성화된 채로 메인 메모리에 남겨두다 보면 메모리 부족 상태가 오기 쉽다. 새로운 앱을 실행시키기 위해 필요한 메모리가 부족해지면 스마트폰의 운영체제는 활성화 되어 있는 앱들 중 몇 개를 선택하여 메모리로부터 삭제하는 수밖에 없다. 이러한 과정을 앱의 ‘비활성화’라고 한다.

메모리 부족 상황에서 활성화 되어 있는 앱들을 무작위로 필요한 메모리만큼 비활성화 하는 것은 좋은 방법이 아니다. 비활성화된 앱들을 재실행할 경우 그만큼 시간이 더 필요하기 때문이다. 여러분은 이러한 앱의 비활성화 문제를 스마트하게 해결하기 위한 프로그램을 작성해야 한다

현재 N개의 앱, A1, ..., AN이 활성화 되어 있다고 가정하자. 이들 앱 Ai는 각각 mi 바이트만큼의 메모리를 사용하고 있다. 또한, 앱 Ai를 비활성화한 후에 다시 실행하고자 할 경우, 추가적으로 들어가는 비용(시간 등)을 수치화 한 것을 ci 라고 하자. 이러한 상황에서 사용자가 새로운 앱 B를 실행하고자 하여, 추가로 M 바이트의 메모리가 필요하다고 하자. 즉, 현재 활성화 되어 있는 앱 A1, ..., AN 중에서 몇 개를 비활성화 하여 M 바이트 이상의 메모리를 추가로 확보해야 하는 것이다. 여러분은 그 중에서 비활성화 했을 경우의 비용 ci의 합을 최소화하여 필요한 메모리 M 바이트를 확보하는 방법을 찾아야 한다.

입력

입력은 3줄로 이루어져 있다. 첫 줄에는 정수 N과 M이 공백문자로 구분되어 주어지며, 둘째 줄과 셋째 줄에는 각각 N개의 정수가 공백문자로 구분되어 주어진다. 둘째 줄의 N개의 정수는 현재 활성화 되어 있는 앱 A1, ..., AN이 사용 중인 메모리의 바이트 수인 m1, ..., mN을 의미하며, 셋째 줄의 정수는 각 앱을 비활성화 했을 경우의 비용 c1, ..., cN을 의미한다

단, 1 ≤ N ≤ 100, 1 ≤ M ≤ 10,000,000이며, 1 ≤ m1, ..., mN ≤ 10,000,000을 만족한다. 또한, 0 ≤ c1, ..., cN ≤ 100이고, M ≤ m1 + m2 + ... + mN이다.

출력

필요한 메모리 M 바이트를 확보하기 위한 앱 비활성화의 최소의 비용을 계산하여 한 줄에 출력해야 한다.

조건

  • 시간 제한 : 1s
  • 메모리 제한 : 128MB

해설

이 문제는 배낭 문제의 변형형이다. M을 초과하면 안되는 일반적인 배낭 문제와 달리 M보다 작으면 안되며, 가치의 최대가 되도록 하는 배낭과는 반대로 비용이 최소가 되어야 하기 때문이다. 따라서 이에 맞게 배낭 문제 알고리즘을 변형하여 해결해주어야 한다.

배낭 문제의 2차원 DP 벡터에는 [행 : 물건 / 열 : 무게 / data : 가치]가 사용되었는데, 이 문제의 경우 무게에 해당하는 메모리의 크기가 제한이 없으므로 값이 매우매우 커질 수 있다. (범위 상으로 메모리 크기는 1억 이상) 이 경우 메모리가 상당히 부족하게 되므로, 제한이 있는 비용을 열의 데이터로 사용하고, 메모리의 크기를 data로 사용해주어 해결할 수 있다. (범위 상으로 비용의 크기는 최대 10000 = 100개의 앱 x 최대 개당 비용 100)

풀이

데이터를 입력받아준다. cost의 경우 dp의 최대 열 개수를 결정해주기 위해 maxCost (모든 앱을 다 비활성화 하는 경우의 cost) 값을 만들어준다.

int N, M;
cin >> N >> M;

vector<int> app(N+1, 0);
vector<int> cost(N+1, 0);

for(int i = 1; i <= N; i++) {
    cin >> app[i];
}
int maxCost = 0;
for(int i = 1; i <= N; i++) {
     cin >> cost[i];
    maxCost += cost[i];
}

2차원 벡터 dp를 만들어준다. 코드의 간소화를 위해 첫 행 / 첫 열에는 0을 삽입해 초기화해주기 위해 N+1, maxCost+1 개의 칸을 만들어준다. 배낭문제 알고리즘과 동일하게 아래 알고리즘을 따른다. 여기에서 각 칸의 dp값은 크면 같은 cost로 더 많은 데이터를 아낄 수 있는 것이므로 dp값이 최대가 되도록 해주어야 한다.

  • 현재 계산하고자 하는 App의 cost가 c 이상인가? (cost[index] ≥ c)
    • true → dp[index][c] = max(dp[index-1][c], dp[index-1][c-cost[index]] + app[index])
    • false → dp[index][c] = max(dp[index-1][c], dp[index][c-1])
vector<vector<int>> dp(N+1, vector<int>(maxCost+1, 0));

for(int index = 1; index <= N; index++) {
    for(int c = 1; c <= maxCost; c++) {
        if(c >= cost[index]) {
            dp[index][c] = max(dp[index-1][c], dp[index-1][c-cost[index]] + app[index]);    
        } else {
            dp[index][c] = max(dp[index-1][c], dp[index][c-1]);
        }        
    }
}

마지막 행에서 M보다 작거나 같은 값을 갖는 dp의 cost 값을 출력해주면 원하는 결과를 얻을 수 있다.

for(int i = 0; i <= maxCost; i++) {
    if(dp[N][i] >= M) {
        cout << i;
        break;
    }
}


코멘트

이 문제도 나한테는 좀 헷갈렸어. 배낭 문제랑 비슷한 접근을 해야한다는것 까지는 파악했는데, 열을 cost로 두고 값을 메모리 크기로 바꾼다는 아이디어를 얻기가 쉽지 않았던 것 같다.


코드

#include <iostream>
#include <vector>

using namespace std;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	int N, M;
	cin >> N >> M;
	
	vector<int> app(N+1, 0);
	vector<int> cost(N+1, 0);
	
	int maxCost = 0;
	for(int i = 1; i <= N; i++) {
	    cin >> app[i];
	}
	for(int i = 1; i <= N; i++) {
	     cin >> cost[i];
	    maxCost += cost[i];
	}
	
	vector<vector<int>> dp(N+1, vector<int>(maxCost+1, 0));
	
	for(int index = 1; index <= N; index++) {
	    for(int c = 1; c <= maxCost; c++) {
	        if(c >= cost[index]) {
	            dp[index][c] = max(dp[index-1][c], dp[index-1][c-cost[index]] + app[index]);    
	        } else {
	            dp[index][c] = max(dp[index-1][c], dp[index][c-1]);
	        }
	        
	    }
	}
	
	for(int i = 0; i <= maxCost; i++) {
	    if(dp[N][i] >= M) {
	        cout << i;
	        break;
	    }
	}
	
	return 0;
}
320x100

'Develop > 알고리즘' 카테고리의 다른 글

[백준] 9184 - 신나는 함수 실행  (0) 2021.12.26
[백준] 5086 - 배수와 약수  (0) 2021.12.26
[백준] 13305 - 주유소  (0) 2021.12.26
[백준] 11047 - 동전 0  (0) 2021.12.26
[백준] 2294 - 동전 2  (0) 2021.12.26
Share Link
reply
반응형
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31