백준 문제

백준 7579(앱) c++

kangyuseok 2023. 2. 16. 13:50
728x90

문제

 

7579번: 앱

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

www.acmicpc.net

현재 사용하고 있는 n개의 메모리 공간과 메모리 제거 비용이 주어지고, 최소 필요한 메모리 공간인 m이 주어지면  

n개의 메모리에서 m만큼 제거하면서 최소 비용이 나오게끔 하는 문제입니다.

예를 들어 n = 5이고 n개의 메모리 공간은 {30, 10, 20, 35, 40} 이고, 각각의 메모리 제거 비용은 {3, 0, 3, 5, 4} 라고 하고

m = 60이라 하면, n개의 메모리 중 {30, 10, 20}을 제거하면 제거 비용은 {3, 0, 3} 이므로 총 6이 되어서 

60의 크기를 제거하기 위한 최소비용이 됩니다.

 

즉, 총 60이상의 메모리를 제거하면서 최소비용이 되게끔하는 것입니다.

이를 다시 풀어쓰면 각 비용당 제거할 수 있는 최대 메모리 크기를 생각하면 문제를 해결할 수 있을 것입니다.

 

이는 가방의 크기(비용)당 넣을 수 있는 최대 무게(메모리의 크기)를 구하는 것과 같습니다.

결국 Knapsack 알고리즘입니다.

 

int memory[101]; //메모리 크기 저장
int cost[101]; //메모리 당 비용 저장
int sum = 0; // 전체 비용

int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)cin >> memory[i];
for (int i = 1; i <= n; i++) {
	cin >> cost[i];
	sum += cost[i];
}

입력 부분입니다.

우리는 현재 입력받은 정보의 최대 비용만큼만 확인하면 되기 떄문에 sum을 이용해 모든 비용의 누적합을 구해줍니다.

 

이제 knapsack알고리즘을 구현할 차례 입니다.

dp[i][j] = i번째 메모리까지 확인하고 j의 비용을 얻을 수 있는 최대의 메모리 입니다.

결국 dp[n][]가 m이상이면 정답입니다.

 

위의 예시를 살펴보면

1번째 메모리 크기 :  30, 비용 3

2번째 메모리 크기 : 10, 비용 0

3번째 메모리 크기 :  20, 비용 3

4번째 메모리 크기 :  35, 비용 5

5번째 메모리 크기 :  40, 비용 4

를 바탕으로 다음과 같은 dp 배열을 만들 수 있습니다.

int dp[101][10001];
for (int i = 1; i <= n; i++) {
	for (int j = 0; j <= sum; j++) {
		if (j - cost[i] >= 0)
			dp[i][j] = max(dp[i-1][j], dp[i - 1][j - cost[i]] + memory[i]);
		dp[i][j] = max(dp[i][j], dp[i - 1][j]);
	}
}

dp배열은 [101][10001]로 설정하였습니다. n의 크기가 최대 100이고, 메모리 한개당 비용의 최대 크기는 100이므로

100 * 100 = 10000이기 때문입니다.

다음은 그냥 knapsack알고리즘과 같습니다.

for (int i = 0; i <= sum; i++) {
	if (dp[n][i] >= m) {
		cout << i;
		break;
	}
}

마지막으로 dp[n][i]의 크기가 m 이상일 때의 i는 n번째 메모리까지 확인하고 i의 비용을 얻을 수 있는 최대 메모리입니다.

i를 출력해 줍니다.


전체 코드입니다.

#include<iostream>
#include<string>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>

#define INF 2000000000
using namespace std;
using ll = long long;
int memory[101];
int cost[101];
int sum = 0;
int dp[101][10001];
int main() {
	ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)cin >> memory[i];
	for (int i = 1; i <= n; i++) {
		cin >> cost[i];
		sum += cost[i];
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= sum; j++) {
			if (j - cost[i] >= 0)
				dp[i][j] = max(dp[i-1][j], dp[i - 1][j - cost[i]] + memory[i]);
			dp[i][j] = max(dp[i][j], dp[i - 1][j]);
		}
	}
	for (int i = 0; i <= sum; i++) {
		if (dp[n][i] >= m) {
			cout << i;
			break;
		}
	}

	return 0;
}