백준 7579 - 앱
Updated:
Java
7579 번 - 앱
문제
- 현재 활성화 되어있는 N개의 앱에 따라 메모리 바이트, 비용이 각각 주어진다.
- M 바이트 이상의 메모리를 추가로 확보해야 한다.
- 비활성화 했을 경우의 비용 ci의 합을 최소화하여 필요한 메모리 M 바이트를 확보하는 방법을 찾아야 한다.
접근 방법
구하려는 문제는, 최소의 비용으로 M 바이트를 확보하는 것이다.
이를 반대로 생각하면, 최대의 비용으로 (전체 바이트 - M 바이트)를 구하면, 최소의 비용의 M바이트를 확보할 수 있다.
따라서, 전형적인 Knapsack Problem
로 (전체 바이트 - M 바이트)를 N개의 메모리로 채우며 그 때의 최대 비용을 구하면 된다.
전체 비용에서 구한 최대 비용을 차감하면, 문제에서 원하는 최소 비용을 구할 수 있게 된다.
하지만, 문제의 조건에서의 N과 M이 다음과 같이 [1 ≤ M ≤ 10,000,000] [1 ≤ N ≤ 100] 범위가 크므로, 단순히 2차원 dp 배열로 해결하려 하면 메모리 초과가 난다.
따라서, 1차원 배열 2개만 설정하고, 서로의 값을 비교하며 KnapSack Problem을 해결하였다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, m, result;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
int[] weight = new int[n + 1];
int[] cost = new int[n + 1];
int wSum = 0, cSum = 0;
stk = new StringTokenizer(br.readLine());
for(int i = 1; i <= n; i++) {
weight[i] = stoi(stk.nextToken());
wSum += weight[i]; // 총 무게를 구한다.
}
stk = new StringTokenizer(br.readLine());
for(int i = 1; i <= n; i++) {
cost[i] = stoi(stk.nextToken());
cSum += cost[i]; // 총 비용을 구한다.
}
int[][] dp = new int[2][wSum - m + 1];
boolean flag = true; // 서로 왕복하는 지점을 앙려주는 배열
int dp1 = 0, dp2 = 0;
for(int i = 1; i <= n; i++) {
if(flag) {
dp1 = 1;
dp2 = 0;
}
else {
dp1 = 0;
dp2 = 1;
}
// 1부터 전체 메모리 - M까지 탐색
for(int j = 1; j <= wSum - m; j++) {
if(j >= weight[i]) { // 가방에 넣을 수 있으면
dp[dp1][j] = Math.max(dp[dp2][j], dp[dp2][j - weight[i]] + cost[i]);
}
else {
dp[dp1][j] = dp[dp2][j];
}
}
flag = !flag; // 방향을 바꾼다.
}
System.out.println(cSum - dp[dp1][wSum - m]);
br.close();
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
같은 스터디 그룹원의 풀이를 듣고 다시 풀어본 문제.
배낭 문제는 조금만 응용이 되어도 헤메는 것 같다.
개선할 점
정석 풀이도 확인해야 한다.