[BOJ][Python][골3][7579] 앱
문제 링크
냅색 알고리즘 공통
모든 냅색 문제의 변수는 아래와 같이 통일해서 풀겠습니다.
- n : 물건의 갯수
- b : 가방의 크기(채울 수 있는 최대 무게 or 채워야하는 최소 무게)
- w : 물건의 무게
- v : 물건의 가치(문제에 따라 최대화 or 최소화)
이 문제의 특징
본 문제에서 사용하는 정확한 의미는 아래와 같습니다.
- n : 앱의 갯수
- b : 비워야 하는 메모리의 크기
- w : 각 앱의 메모리 크기
- v : 각 앱의 비활성화 비용
이 문제의 특징은 세 가지 입니다.
- 각 앱을 중복 선택(삭제)할 수 없다.
- 채워야하는 최소 w가 주어진다.
- v를 최소화해야 한다.
시간 초과 풀이
- dp[i] : i weight를 만들기 위해 필요한 최소 비용
- dp 초기화 : 최소값을 찾는 문제이기 때문에 dp[:] = INF
- dp[0] : 0 weight를 만들기 위한 비용은 0. 최소값을 찾기위해 꼭 필요!
- s : 모든 앱의 메모리의 합.
- 정답 : max(dp[b:s+1]). b weight 이상 공간을 만들었을 때 최소 비용
아래 코드를 사용하면 다음과 같은 방법으로 갱신됩니다.
1
2
3
4
for i in range(0, n): # 지울 앱의 index.
for j in range(s, -1, -1): #
if j - w[i] >= 0:
dp[j] = min(dp[j], dp[j - w[i]] + v[i])
- i는 0일 때
- dp[30] = min(dp[30], dp[0] + 3)에서만 갱신이 일어남
- dp[30] = min(INF, 0+3) = 3
- i는 1일 때
- dp[40] = min(dp[40], dp[30]+0) = min(INF, 3) = 3
- dp[10] = min(dp[10], dp[0]+0) = 0
dp[i] | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
초기값 | 0 | INF | INF | INF | INF | INF | INF | INF | INF | INF | INF | INF | INF |
(6,3) | 0 | 3 | |||||||||||
(2,0) | 0 | 0+0 | 3 | 3+0 | |||||||||
(4,3) | 0 | 0 | min(3,0+3) | 3 | 6 | 6 | |||||||
dp[i] | 0 | INF | 0 | INF | INF | INF | 3 | INF | 3 | INF | 6 | INF | 6 |
하지만 이 경우 $O(n * sum_of_memory) = O(1e2 * 1e7)$의 시간 복잡도를 가져 시간초과가 납니다.
시간초과 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys
from math import sqrt, ceil
from bisect import bisect_left, bisect_right
from operator import itemgetter
from collections import Counter, deque
from copy import deepcopy
# sys.stdin = open("input.txt", "r")
# N, Bag, Weight, Value
INF = 1e9
n, b = map(int, sys.stdin.readline().split())
w = list(map(int, sys.stdin.readline().split()))
v = list(map(int, sys.stdin.readline().split()))
s = sum(w)
dp = [INF] * (s + 1)
dp[0] = 0
for i in range(0, n):
for j in range(s, -1, -1):
if j - w[i] >= 0:
dp[j] = min(dp[j], dp[j - w[i]] + v[i])
print(min(dp[b:s + 1]))
정답 풀이
$O(n * sum_of_cost)$의 시간 복잡도를 가지는 dp 풀이를 사용하면 비슷한 알고리즘으로 시간을 많이 줄일 수 있습니다.
- dp[i] = j : i만큼 비용을 지불할 때 얻을 수 있는 최대 메모리의 양
- dp[i] = max(dp[i], dp[i-v[j]]+w[j])
마지막으로 더해지는 비용이 어떤 앱을 취소함으로써 더해진 것인지 고려하는 방법을 사용합니다.
정답은 최소 메모리를 얻을 수 있는 최소 비용을 구하면 됩니다.
정답 코드
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
import sys
from math import sqrt, ceil
from bisect import bisect_left, bisect_right
from operator import itemgetter
from collections import Counter, deque
from copy import deepcopy
# sys.stdin = open("input.txt", "r")
# N, Bag, Weight, Value
INF = 1e9
n, b = map(int, sys.stdin.readline().split())
w = list(map(int, sys.stdin.readline().split()))
v = list(map(int, sys.stdin.readline().split()))
s = sum(v)
dp = [0] * (s + 1)
dp[0] = 0
for i in range(0, n):
for j in range(s, -1, -1):
if j - v[i] >= 0:
dp[j] = max(dp[j], dp[j - v[i]] + w[i])
ans = 0
while ans < s and dp[ans] < b:
ans += 1
print(ans)
Success Notice: 수고하셨습니다.
Leave a comment