Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Algorithm] Knapsack 알고리즘 #70

Merged
merged 3 commits into from
Sep 4, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions contents/algorithm/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [분할 정복법 (Divide and Conquer)](#분할-정복법-divide-and-conquer))
- [탐욕 알고리즘 (Greedy)](#탐욕-알고리즘-greedy)
- [동적 계획법 (Dynamic Programming)](#동적-계획법-dynamic-programming)
- [0-1 Knapsack](#0-1-knapsack)

</details>

Expand Down Expand Up @@ -537,3 +538,57 @@ if (currentRow - rowNum == abs(colNum - board[rowNum]))

> **"큰 문제를 여러개의 하위 문제로 나누어 푼다"** 라는 점에서
> DP는 그 하위의 값이 계속 변하고, DAC는 변하지 않는다는 차이점이 있다.

### 0-1 Knapsack

`Knapsack` 알고리즘은 크게 두가지로 나눌 수 있다.

1. Fractional Knapsack
2. 0-1 Knapsack

`Fractional Knapsack`의 경우 탐욕 기법을 사용해서 해결할 수 있다.
반면 `0-1 Knapsack`의 경우 탐욕 기법을 통해서는 _정해를 보장할 수 없고_ **동적 프로그래밍**을 사용해서 해결할 수 있다.

#### 0-1 Knapsack 이란 ?

1. N개의 보석이 있다.
2. 보석들은 각 보석마다 가격(V)과 무게를 가지고 있다.
3. 도둑이 보석을 훔치려고 한다! 하지만 도둑의 가방에는 정해진 무게(W) 밑으로만 담을 수 있다.
4. 도둑이 배낭 안에 담은 보석의 가격의 합이 최대가 되도록 하라.

동적 계획법의 기본적인 메커니즘에 의해, 이전 단계에서 구했던 최적해가 다음 단계에서 최적해를 구하는데 포함됨을 기억하며 점화식을 설계해보자.

```c
KNAPSACK(i, w) : 1~i 번호까지의 보석 중 배낭의 최대 무게가 w일 때의 가질 수 있는 최대의 보석가격합.
```

이러한 식을 설계한다고 했을 때, 우리가 원하는 최적해는 `KNAPSACK(N, W)`가 될 것이다.

배낭 무게를 1부터 W까지 늘려가며, 보석을 넣는다고 해보자.

이 때 다음 보석을 넣기 전 고려해야할 경우의 수가 3가지 있다.

1. 다음 보석을 배낭에 담을 수 없다.
2. 다음 보석을 배낭에 담을 수 있다.
2-1. 다른 보석을 빼고 현재 보석을 담는다.
2-2. 다른 보석과 함께 현재 보석을 담는다.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분이 한줄로 나옵니다. 의도하신 것과 다른 것 같아요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사합니다. 수정했어요 🎉


보석을 담을 수 없는 조건은 다음과 같다.

1. 현재 보석의 무게가 가방의 무게보다 무겁다.
2. 다른 보석을 빼고 넣은 무게가 이전 단계의 무게보다 가볍다.

`KNAPSACK(N, W)`는 결국 `KNAPSACK(N-1, w)`와 연관을 갖게 된다.
즉, 이전 보석 번호의 최적해 값을 사용하여 구하게 되는 것이다.

위의 조건들을 고려하여 점화식을 세워볼 수 있겠다.

```c
(if w[i] > w) KNAPSACK(i-1, w)
KNAPSACK(i, w) =
(if w[i] <= w) max(KNAPSACK(i-1, w), KNAPSACK(i-1, w-w[i]) + V[i])
```

위의 점화식을 사용해 보석 번호 1부터 N까지, 배낭 무게를 1부터 W까지 반복하며 이차원 배열을 채워나가면 된다.

이러한 풀이방법을 사용한다면 배낭문제를 `O(N*W)`의 시간복잡도로 해결 할 수 있게 된다.