프로필사진

Go, Vantage point

가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.


Github | https://github.com/overnew/

Blog | https://everenew.tistory.com/





티스토리 뷰

반응형

문제

 

https://www.acmicpc.net/problem/12920

 

12920번: 평범한 배낭 2

첫 번째 줄에 N, M (1 ≤ N ≤ 100, 1 ≤ M ≤ 10,000) 이 빈칸을 구분으로 주어진다. N은 민호의 집에 있는 물건의 종류의 수이고 M은 민호가 들 수 있는 가방의 최대 무게다. 두 번째 줄부터 N개의 줄에

www.acmicpc.net

 

풀이

 

solved.ac 난이도: Platium5

 

 

[백준] 평범한 배낭(12865)의 다음 단계 문제로 같은 물건이 여러 개 있는 경우이다.

 

이 문제를 일반적인 배낭(Knapsack) 문제와 동일하게 해결하려 시간 복잡도가  O(N* K *M)이기 때문에 시간 초과가 발생한다.

따라서 다음과 같은 최적화가 필요하다.

 

물건의 개수를 2의 제곱수의 합으로 분할하는 기법을 사용한다.

만약 물건이 11개 있다면 2의 제곱수의 합으로는 다음과 같이 나타낼 수 있다.

1(2^0) + 2(2^1) + 8(2^3) = 11

 

이때 각각의 개수로 분리된 물건 A를 하나의 물건으로 생각해보자.

물건 A의 무게를 w, 만족도를 c라고 하면

A가 4개로 묶어 하나의 물건이라 생각하면 이 물건의 무게는 w*4, 만족도는 c*4가 되는 식이다.

 

단 이런 구현에는 다음과 같은 문제가 생길 수 있다.

11 이하인 2의 제곱수로 물건을 모두 분해하면 1/ 2/ 4/ 8 개의 묶음이 생기는데 모든 묶음이 모두 선택되면 1 + 2 + 4 + 8 = 15로 11을 초과한다.

 

 

따라서 다음과 같이 물건의 개수를 분할해 주었다.

1
2
3
4
for(int i=k /*물건의 개수*/; i>0 ; i >>=1){
  int part = i -(i>>1);
  divided_item.push_back({w*part, c*part});
}
cs

 

물건의 개수가 11개라면 다음과 같이 분할된다.

1. 11 - 5 = 6

2. 5 - 2 = 3

3. 2 - 1 = 1

4. 1 - 0 = 1

 

6/ 3/ 1 /1

이 4가지 수로 1 ~ 11까지의 모든 수를 조합할 수 있고 4가지 모든 수의 합이 11을 초과하지도 않는다.

 

따라서 모든 물건을 위와 같이 분할하여주고 일반적인 knapsack알고리즘을 진행해주면 답을 구할 수 있다.

이러한 분할은 각 물건을 log(K)개로 만들 수 있기 때문에 시간복잡도는 O(N*log(K)*M)가 된다.

 

 

너무 어렵다...

이런 최적화는 어떻게 생각해 내는 걸까?

 

참조 풀이

코딩하기 좋은날 블로그 해설

 

코드

 

 

반응형
댓글
반응형
인기글
Total
Today
Yesterday
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함