728x90
반응형

여행 짐 싸기

문제 정보

시간 제한 메모리 제한
2000ms 65536kb

문제

여행을 떠나기 전날까지 절대 짐을 싸지 않는 버릇이 있는 재훈이는 오늘도 비행기 타기 전날에야 가방을 싸기 위해 자리에 앉았습니다. 비행기 규정상 재훈이는 캐리어를 하나만 가지고 갈 수 있는데, 아무래도 가져가고 싶은 물건들이 캐리어 안에 다 들어가지 않을 것 같습니다. 재훈이는 가져가고 싶은 각 물건들의 부피와 얼마나 필요한지를 나타내는 절박도를 조사해 다음과 같은 목록을 만들었습니다.

물건 노트북 컴퓨터 카메라 XBOX365 커피그라인더 아령 백과사전
부피 4 2 6 4 2 10
절박도 7 10 6 7 5 4

캐리어의 용량이 정해져 있기 때문에 가져갈 수 있는 물건들의 부피 합은 캐리어의 용량 w 이하여야 합니다. 이때 절박도를 최대화할 수 있는 물건들의 목록을 계산하는 프로그램을 작성하세요.

입력

입력의 첫 줄에는 테스트 케이스의 수 C (1≤C≤50)가 주어집니다. 각 테스트 케이스의 첫 줄에는 가져가고 싶은 물건의 수 N (1≤N≤100)과 캐리어의 용량 W (1≤W≤1000)가 주어집니다. 그 이후 N줄에 순서대로 각 물건의 정보가 주어집니다. 한 물건에 대한 정보는 물건의 이름, 부피, 절박도 순서대로 주어지며, 이름은 공백 없는 알파벳 대소문자 1글자 이상 20글자 이하의 문자열, 부피와 절박도는 1000 이하의 자연수입니다.

출력

각 테스트 케이스별 출력의 첫 줄에는 가져갈 수 있는 물건들의 최대 절박도 합과 가져갈 물건들의 개수를 출력합니다. 이후 한 줄에 하나씩 각 물건들의 이름을 출력합니다. 만약 절박도를 최대화하는 물건들의 조합이 여럿일 경우 아무 것이나 출력해도 좋습니다.

예제 입력

2
6 10
laptop 4 7
camera 2 10
xbox 6 6
grinder 4 7
dumbell 2 5
encyclopedia 10 4
6 17
laptop 4 7
camera 2 10
xbox 6 6
grinder 4 7
dumbell 2 5
encyclopedia 10 4

예제 출력

24 3
laptop
camera
grinder
30 4
laptop
camera
xbox
grinder

문제 풀이

  1. 다음 물건을 고를때와 고르지 않을 때를 비교하여 최대 절박도를 리턴해주는 최대 절박도 계산 (pack) 함수를 만든다.
  2. 현재 순번 N과 그 다음 순번 N + 1을 pack 함수를 호출하여 비교하여 같지 않은 경우 결과값 (picked)에 담아주는 재귀 함수 (recursive_pack)를 만든다.
  3. 재귀 함수 (recursive_pack)를 호출하여 결과 값을 출력하는 solution 함수를 만들어 최초 호출한다.

전체 코드

def pack(total_weight, weights, needs, index):
    if index == len(weights) - 1 or total_weight == 0:
        return 0

    if weights[index + 1] > total_weight:
        return pack(total_weight, weights, needs, index + 1)

    return max(needs[index] + pack(total_weight - weights[index], weights, needs, index + 1), pack(total_weight, weights, needs, index + 1))
               
               
def recursive_pack(total_weight, weights, needs, index, picked = []):
    
    if index == len(weights) - 1 or total_weight == 0:
        return picked
        
    if pack(total_weight, weights, needs, index) == pack(total_weight, weights, needs, index + 1):
        return recursive_pack(total_weight, weights, needs, index + 1, picked)
    else:
        picked.append(index)
        return recursive_pack(total_weight - weights[index], weights, needs, index + 1, picked)
        
def solution(total_weight, names, weights, needs):
    sum_needs = 0
    pack_names = []
    rst = recursive_pack(total_weight, weights, needs, 0, [])
    for index in rst:
        pack_names.append(names[index])
        sum_needs += needs[index]
        
    print(sum_needs, len(pack_names))
    for pack_name in pack_names:
        print(pack_name)
        
        
# 예제 1)
names = ['lasttop', 'camera', 'xbox', 'grinder', 'dumbell', 'encyclopedia']
needs = [7, 10, 6, 7, 5, 4]
weights = [4, 2, 6, 4, 2, 10]
total_weight = 10
solution(total_weight, names, weights, needs)
# lasttop
# camera
# grinder
# 24

# 예제 2)
names = ['lasttop', 'camera', 'xbox', 'grinder', 'dumbell', 'encyclopedia']
needs = [7, 10, 6, 7, 5, 4]
weights = [4, 2, 6, 4, 2, 10]
total_weight = 17
solution(total_weight, names, weights, needs)
# lasttop
# camera
# xbox
# grinder
# 30

참고자료

728x90
반응형

'알고리즘 > 동적 계획법' 카테고리의 다른 글

[알고리즘] 다이나믹 프로그래밍  (0) 2020.11.08