15.6 연습 문제¶
15.6.1 개념 확인¶
1. 매번 가장 큰 동전을 고르면 항상 최선인가¶
동전의 액면가는 [1, 7, 10]이며, 목표 금액은 14다.
- ‘남은 금액을 넘지 않는 가장 큰 액면가의 동전을 매번 고른다’는 규칙을 실행하고 선택한 동전을 적어 보자.
- 동전을 더 적게 사용하는 방법이 있는가? 있으면 하나를 적고, 없으면 이유를 설명하라.
- 이 결과로 해당 탐욕 전략이 어떤 동전 액면가에서든 올바르다고 할 수 있는가?
참고 답안
-
탐욕 방식은
10 + 1 + 1 + 1 + 1을 차례대로 선택하여 총 5개의 동전을 사용한다. -
더 적게 사용하는 방법이 있다.
7 + 7이면 동전 2개만 필요하다. -
그럴 수 없다. 이 반례는 임의의 동전 액면가에서 현재 고를 수 있는 가장 큰 액면가를 매번 선택한다고 해서 반드시 최소 동전 개수를 얻는 것은 아님을 보여 준다. 당장 가장 큰 것을 선택하면 이후에 더 좋은 조합을 만들 기회를 잃을 수 있다.
2. 배낭에 어떤 물건을 먼저 넣어야 하는가¶
용량이 4킬로그램인 배낭에 다음 물건을 넣을 수 있다. 물건의 일부만 넣어도 되며, 얻는 가치는 넣은 무게에 비례한다.
- 물건 A: 무게 4킬로그램, 가치 20
- 물건 B: 무게 3킬로그램, 가치 18
- 두 물건의 킬로그램당 가치는 각각 얼마인가? 어느 물건을 먼저 넣어야 하는가?
- 분할 가능한 배낭 문제의 탐욕 전략으로 배낭을 가득 채우면 최종 가치는 얼마인가?
- 물건을 나눌 수 있고 배낭이 총무게를 제한하는 상황에서는 물건을 고를 때 총가치와 킬로그램당 가치 중 무엇을 비교해야 하는가? 이유도 설명하라.
참고 답안
-
A의 킬로그램당 가치는
20 ÷ 4 = 5, B의 킬로그램당 가치는18 ÷ 3 = 6이다. 따라서 단위 무게당 가치가 더 높은 B를 먼저 넣어야 한다. -
먼저 B를 전부 넣으면 3킬로그램을 차지하고 가치 18을 얻는다. 남은 용량 1킬로그램에는 A를 1킬로그램 넣어 가치 5를 얻는다. 최종 가치는
18 + 5 = 23이다. -
배낭은 총무게를 제한하고 물건을 나눌 수 있으므로 단위 무게당 가치를 비교해야 한다. A는 총가치가 더 높지만 킬로그램당 가치는 B보다 낮다. A부터 넣어 배낭을 채우면 가치 20밖에 얻지 못한다.
3. 두 포인터를 다음에 어떻게 움직여야 하는가¶
칸막이 높이가 [1, 8, 6, 2, 5]일 때 양 끝에서 시작하는 두 포인터로 최대 용량을 찾는다.
용량은 ‘두 칸막이 중 더 낮은 높이 × 두 칸막이의 인덱스 차이’다.
- 처음에는 왼쪽 포인터가 인덱스 0, 오른쪽 포인터가 인덱스 4에 있다. 현재 용량은 얼마인가? 다음에는 어느 포인터를 움직여야 하는가?
- 1번에서 선택한 대로 한 번 움직이면 두 포인터는 각각 어느 인덱스에 있는가? 이때 용량은 얼마이며, 다음에는 어느 포인터를 움직여야 하는가?
- 현재 두 칸막이에서 더 낮은 쪽의 포인터를 움직일 수도 있고, 더 높은 쪽의 포인터를 움직일 수도 있다. 어느 쪽을 움직여야 더 큰 용량을 얻을 가능성이 남는가? 이유는 무엇인가?
참고 답안
-
현재 용량은
min(1, 5) × (4 - 0) = 4다. 왼쪽 칸막이가 더 낮으므로 왼쪽 포인터를 움직인다. -
왼쪽 포인터를 움직이면 두 포인터는 각각 인덱스 1과 4에 있다. 현재 용량은
min(8, 5) × (4 - 1) = 15다. 오른쪽 칸막이가 더 낮으므로 다음에는 오른쪽 포인터를 움직인다. -
더 낮은 칸막이 쪽의 포인터를 움직여야 더 큰 용량을 얻을 가능성이 남는다. 더 높은 칸막이를 움직이면 두 칸막이 사이의 거리는 반드시 줄어드는 반면, 용기의 높이는 여전히 움직이지 않은 낮은 칸막이에 의해 제한되므로 그대로이거나 더 낮아질 뿐이다. 따라서 용량은 움직이기 전보다 커질 수 없다. 낮은 칸막이를 움직여야만 더 높은 칸막이를 만날 기회가 생긴다.
15.6.2 프로그래밍 연습¶
1. 분할 가능한 배낭 문제¶
길이가 같은 배열 wgt와 val이 주어진다. wgt[i] > 0, val[i] >= 0이며 배낭 용량은 cap >= 0이다.
각 종류의 물건은 하나씩만 있지만, 그중 일부만 넣어도 된다.
얻는 가치는 넣은 무게가 해당 물건의 총무게에서 차지하는 비율로 계산한다. 탐욕 알고리즘을 사용하여
배낭에서 얻을 수 있는 최대 총가치를 실수로 반환하라.
풀이 힌트
- 먼저 각 물건의 단위 무게당 가치 val[i] / wgt[i]를 계산한다. 나눗셈 결과의 소수 부분을 유지해야 한다.
- 단위 무게당 가치가 높은 물건부터 배낭에 넣는다.
- 남은 용량이 현재 물건의 무게보다 작으면 배낭을 정확히 채우는 만큼만 넣고 끝낸다.