백준

백준 12865번: 평범한 배낭

츄츄츄츄츄츄츄 2022. 12. 19. 00:52

문제링크: 12865번: 평범한 배낭 (acmicpc.net)

 

12865번: 평범한 배낭

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

www.acmicpc.net

 

이 문제는 제한 무게가 있는 배낭에 물품 당 무게, 가치가 각각 주어진 물품을 가장 효율적으로 넣는 문제이다. 이 문제는 DP를 활용하여 풀 수 있었다. 나는 1차원 배열의 DP를 사용해서 풀었지만 인터넷을 보니 2차원 배열의 DP를 사용해 푸는 방법도 있었다. 그런데 1차원 배열을 사용하는것이 더 간단하고 메모리나 시간복잡도 상에서도 더 좋아 보였다.

import sys

N,K=map(int,sys.stdin.readline().rstrip().split())

lst=[]
values=[0 for _ in range(K+1)]
for _ in range(N):
    lst.append(list(map(int,sys.stdin.readline().rstrip().split())))

for i in range(N): #물품 0부터 N-1까지
    w=lst[i][0]
    v=lst[i][1]
    valuescopy=values[:]
    for j in range(K):
        if j+w<=K:
            if values[j]!=0 or j==0: #가방에 뭔가 담겨져 있는 경우 또는 빈 경우
                if values[j+w]<values[j]+v:
                    valuescopy[j+w]=values[j]+v
    values=valuescopy

print(max(values))

values리스트의 각 인덱스가 물품들을 합친 무게, 값이 그 물품들의 가치 합을 뜻한다. 일단 N개의 물품 (i인덱스) 을 돌아보면서 values의 인덱스가 0일때 (빈 배낭일때)와 values의 값이 0이 아닌 인덱스(물품이 들어있을 때) j 에서 그 물품을 넣어본다. 물품을 넣었을 때의 인덱스는 j+w가 될 것이고 values[j+w]의 값이 values[j]+v 보다 작으면 동일무게 대비 물품을 넣었을 때의 가치가 더 크단 것이므로 values의 복사본인 valuescopy를 업데이트 해준다. 위 과정을 기존에 물품이 들어있던 경우 만큼 반복해 주고 그 물품 i 에 대한 탐색이 끝나면 values를 업데이트 해 준다.

 

valuescopy복사본을 만들어 준 이유는 만약 values원본을 업데이트 해 준다면 한 물품만 계속해서 넣는 경우가 생기기 때문이다. 예를들어 무게가 1, 가치가 100인 물품을 처음으로 탐색한다면 values[1]=100, 그리고 다음 반복을 통해 values[2]=200, values[3]=300 .. 이렇게 될 것이다. 처음에 이것을 생각하지 못해 오답이 되었었다. 이 풀이 방법의 특이사항은 values는 그 인덱스의 무게만큼 물품을 딱 맞게 넣었을때의 최대 가치가 저장되므로 values의 마지막 인덱스가 항상 답이 되는건 아니다. 그러므로 max(values)를 출력해 주어야 가치의 최대값이 나오게 된다.

'백준' 카테고리의 다른 글

백준 11444번: 피보나치 수 6 (Graph, Matrix)  (0) 2022.12.30
백준 13172번: Σ (모듈러 역원)  (0) 2022.12.20
백준 2638번: 치즈  (0) 2022.12.17
백준 9465번: 스티커  (0) 2022.12.17
백준 2448번: 별찍기 - 11  (0) 2022.12.15