-
[알고리즘] 배낭 문제 (Knapsack Problem) - 부분 배낭 문제 (Fractional Knapsack)Major/Algorithms 2022. 4. 18. 21:19
배낭 문제는 한정된 배낭에 무게와 가치가 정해져있는 물건을 담을 때 담은 물건이 최대의 가치를 갖도록 물건을 정하는 문제이다
- n개의 물건 집합 S={1, 2, 3, 4,..., n} (물건번호)
- 배낭의 최대 무게 M
- 물건 i의 무게 w={w1, w2, w3,..., wi}
- 물건 i의 이윤 Pi이렇게 있을 때
- ∑ wi*xi ≤ M (물건의 무게 총합 ≤ 배낭의 최대 무게)
- ∑ Pi*xi => 최대 (물건 총합 가치 최대)여야한다
여기서 xi의 범위에 따라 구현 방법이 달라지는데 두 가지 방법이 있다1) xi 의 값이 0 ≤ xi ≤ 1 : 부분 배낭 문제
xi 가 1/3이라면 물건을 1/3 만큼 담는다는 얘기이다
- 그리디 알고리즘을 이용한다 (0-1 배낭문제보다 비교적 수월하다)2) xi 의 값이 0 or 1 만 허용 : 0-1 배낭문제
xi가 0일 때 > 물건을 담지 않는다
xi가 1일 때 > 물건을 담을 수 있다
- 동적 계획 알고리즘 (다이나믹 프로그래밍)을 이용한다
이번 글에서는 (1) xi 의 값이 0 ≤ xi ≤ 1 : 부분 배낭 문제 를 보도록 하자
예시를 통해 보면 더 쉬울것이다① xi 의 값이 0 ≤ xi ≤ 1 : 부분 배낭 문제
- 현재 배낭의 최대 무게 = 40그램
- 물건은 아래와 같다(1) 단위 그램 당 가치를 구한다
(2) 리스트 S에 단위 그램당 가치를 내림차순으로 정렬한다
(3)
- L = 배낭에 담을 물건 리스트
- w=0 (배낭의 담긴 물건 무게의 합)
- v=0 (배낭에 담긴 물건 가치의 합)(4) S에서 단위 그램당 가치가 가장 큰 물건 x을 가져온다
(5)
- w + (x의 무게) ≤ 배낭 무게 한도 (C)
- w = w + (x의 무게) / v= v+(x의 가치) / x를 S에서 제거(6) 4,5번을 반복한다
(7) 배낭에 물건을 부분적으로 담을 여유가 있으면 ( if C-w > 0)
(8) 배낭에 담을 수 있는 물건(C-w) 만큼만 담는다PSEUDO CODE
FractionalKnapsack(Item *arr, int capacity) { 각 물건의 단위 무게당 가치를 계산한다. 단위 무게당 가치를 기준으로 내림차순 정렬하여 저장한다. int weight = 0; // 배낭에 담긴 무게 int value = 0; // 배낭에 담긴 가치의 총합 Item highest = 단위 무게당 가치가 가장 큰 물건; Item *list; // 배낭에 담긴 물건의 리스트 while (weight + highest.weight <= capacity) { highest를 list에 추가한다. weight += highest.weight; value += highest.value; highest를 arr에서 제거한다. 새로운 highest를 선정한다. } if (capacity > weight) { highest를 (capacity - weight)만큼만 list에 추가한다. value += capacity - weight; } return list, value; }
시간복잡도
n개의 물건의 단위 그램당 가치를 계산하는 건 O(n)
물건의 그램 당 가치 계산 한 것을 정렬하는건 O(nlogn)
나머지 수행 시간은 O(1) 시간 소요된다따라서 시간복잡도 : O(nlogn)
'Major > Algorithms' 카테고리의 다른 글
[알고리즘] 작업 스케줄링 (Job Scheduling) 문제 (0) 2022.04.18 [알고리즘] 집합 커버 문제 (Set Cover) (0) 2022.04.18 [이취코] ch09-2. 최단 경로 / 다익스트라 알고리즘 (힙 이용) (0) 2022.04.18 [이취코] Ch09-1. 최단경로 / 다익스트라 알고리즘 (0) 2022.04.18 [알고리즘] 합병(병합)정렬, Merge Sort 개념 및 구현 (0) 2022.04.13