본문 바로가기

boj

백준 12865 평범한베낭

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

 

12865번: 평범한 배낭

첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000)

www.acmicpc.net

첫 풀이

2차원 배열을 이용해서 풀음

dp[i][j]= i번째 물건까지 봤을때,  무계 j를 만족하는 가장 큰 가치

 

소스

import sys
input=sys.stdin.readline
n,k=map(int,input().split())

wv=[[0,0]]+[[*map (int,input().split())]for _ in range(n)]

dp=[[0 for _ in range(k+1)]for _ in range(n+1)]

#dp[i][j]=i번째 물건까지 봤을때, 무계가 j인 배낭의 최대가치

for i in range(1,n+1):
    for j in range(1,k+1):
        if j-wv[i][0]>=0:
            dp[i][j]=max(dp[i-1][j-wv[i][0]]+wv[i][1],
            dp[i-1][j])
        else:
            dp[i][j]=dp[i-1][j]

print(dp[-1][-1])

그런데 다른사람들 풀이를 보다 보니, 2배는 효율적인 알고리즘이 있었다.

2차원 배열이 아니라 1차원 배열로 푸는 방식인데,

뒤에서부터 업데이트하면서 앞의 값을 쓰고, 계속 갱신시켜나가는 방법이다.

진짜 부족함을 느낀다.

import sys
input=sys.stdin.readline
n,k=map(int,input().split())
dp=[0 for _ in range(k+1)]
# dp[i]= 무계가 i일때의 최댓값
for _ in range(n):
    w,v=map(int,input().split())
    for i in range(k,w-1,-1): #이전값들을 써먹기 위해뒤에서부터 돌면서
                            #만일 w>=k이면, 반복문안돔
        dp[i]=max(dp[i],dp[i-w]+v) 
        # 무계가 i일때의 최댓값은
        # {지금 주어진물건을 포함하지 않았을때의 최댓값과
        # 무계가 i-w 즉 지금물건을 포함할 수 있는 경우 +지금물건의 가치}
        # 의 최댓값이다.

print(dp[-1])

예제

4 7 #n,k
6 13
4 8
3 6
5 12

 

초기 dp

인덱스는 무계를 나타냄

0 0 0 0 0 0 0 0

6 13일때

7,8번째의 값이 변경됨

0 0 0 0 0 0 0 13
0 0 0 0 0 0 13 13

4 8일때

총 8,7,6,5를 돌면서 업데이트 (8,7은 13이 더 크니깐, 6,5만 업데이트)

0 0 0 0 0 8 13 13
0 0 0 0 8 8 13 13

3,6일때

마찬가지로 8에서 3까지 도는데, dp[8-3]+6이  14로 13보다 크므로, dp[8]업데이트

3업데이트

0 0 0 0 8 8 13 14
0 0 0 6 8 8 13 14

5 12일때

마찬가지로 8에서 5까지 도는데, dp[5-5]+12=0+12=12이므로,

5번째 인덱스 변경됨

0 0 0 6 8 12 13 14

우리가 찾는건 dp[i-1]

 

'boj' 카테고리의 다른 글

백준 14500 테트로미노  (0) 2022.04.25
백준 1707 이분 그래프  (0) 2022.04.23
백준 7562 나이트의 이동  (0) 2022.04.21
백준 14888 연산자 끼워넣기  (0) 2022.04.21
백준 17114 하이퍼 토마토  (0) 2022.04.20