백준 12865 - 평범한 배낭 (Python3)
코드
n, k = map(int, input().split())
# 가지고갈 물건의 무게와 가치를 담을 리스트
# 처음 0,0 값을 넣어서 인덱스를 편하게 관리할 수 있음
ob = [[0, 0]]
# DP 테이블
# k+1만큼 0을 넣고, n+1만큼 행을 갖게 만듬
# 마찬가지로 인덱스를 편하게 관리할 수 있음
pack = [[0 for _ in range(k+1)] for _ in range(n+1)]
for _ in range(n):
    # w, v 입력받음
    ob.append(list(map(int, input().split())))
# 1~n, 1~k 만큼 반복
for i in range(1, n+1):
    # j : 배낭에 담을 수 있는 최대 무게
    for j in range(1, k+1):
        
        # 무게와 가치를 뽑아냄
        w = ob[i][0]
        v = ob[i][1]
        
        # i번째 물건의 무게보다 작다 => 배낭이 담을 수 있는 무게를 초과했다
        # 당연히 못 넣으므로 그전 DP 테이블의 값을 그대로 가져옴
        if j < w:
            # 바로 전까지의 누적 v값을 그대로 가져옴
            pack[i][j] = pack[i-1][j]
        # 크거나 같다 => 배낭에 추가로 더 넣을 수 있다
        else:
            # pack[i-1][j-w] + v의 의미
            # i번째 물건을 넣지 않는 경우, 배낭에 담을 수 있는 최대 무게는 
            # i번째 물건의 무게를 뺀 나머지가 되므로 => j-w가 된다
            # pack[i-1][j-w]는 i번째 물건을 넣기 전까지의 최대 효용 가치가 되고
            # 여기에 v (i번째 물건의 가치)를 더해주면 원하는 값을 구할 수 있다
            
            # 위의 주석 과정을 넣은 경우와 넣지 않은 경우 둘 중 더 큰 값을 DP 테이블에 업데이트 해줌
            pack[i][j] = max(pack[i-1][j], pack[i-1][j-w] + v)
            
print(pack[n][k])
문제 해설
DP 문제에서 매우 유명한 냅색(배낭) 문제. (냅색 문제 나무위키 참고)
이 문제를 접하기 전까지 이 유형의 문제가 유명하다는 것 조차 알지 못했다 ㅠㅠ
풀이 순서
- DP 테이블을 2차원 리스트로 생성하여 보유한 물건들을 순서대로 최대 허용 무게만큼 하나씩 넣어주면서 최대 효용 가치를 계산한다
- 무게가 초과되면 이전 아이템을 빼거나 기존 그대로 가지는 방법 중 하나를 선택하여 DP 테이블을 계속해서 업데이트 해준다
위 두 과정을 반복하여 거쳐 마지막 DP 테이블까지 모두 업데이트 시키면 최종적으로 가치합의 최댓값을 구할 수 있다.
댓글남기기