Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 코루틴
- MyVoca
- relay
- GitHub
- 프로그래머스
- Rxjava
- Hilt
- androidStudio
- 코드포스
- 백준
- ProGuard
- 암호학
- Compose
- TEST
- android
- Coroutine
- pandas
- Codeforces
- Python
- MiTweet
- boj
- livedata
- AWS
- 쿠링
- activity
- architecture
- Gradle
- textfield
- Coroutines
- Kotlin
Archives
- Today
- Total
이동식 저장소
12920. 평범한 배낭 2 본문
솔루션을 보고 해결한 문제이며, 공부용으로 기록함을 밝힙니다.
12920번: 평범한 배낭 2 (acmicpc.net)
12865. 평범한 배낭 문제에서는 모든 물건이 1개였는데, 이 문제에서는 물건이 여러 개일 수 있다. 여러 개의 물건을 처리하는 가장 쉬운 방법은 서로 다른 물건으로 취급하여 푸는 것이다. 그러나 이렇게 풀면 물건이 최대 1만 개이고, 배낭의 무게가 최대 1만이므로 총 1억 번의 계산을 해야 한다. 이러면 시간 초과가 난다.
따라서 물건을 하나씩 따로 취급하면 안 된다. 가짓수를 덜 나누면서도 물건을 고르는 모든 경우의 수를 만들 수 있어야 한다.
이 문제에서 사용하는 해법은, 물건 수를 2의 거듭제곱 꼴로 나누는 것이다. 예를 들어 물건 7개를 1, 2, 4개로 쪼개면, 0개부터 7개까지의 모든 경우의 수를 만들 수 있다.
정확히는 아래 코드처럼 나누면 된다. 이렇게 하면 2의 거듭제곱 합으로 나타낼 수 없는 나머지까지 포함할 수 있다. 예를 들어 $10,000$은 다음과 같이 나뉜다.
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 1809
int square = 1;
while (k > 0)
{
int count = std::min(k, square);
// 물건 push
k -= count;
square <<= 1;
}
물건이 최대 14개로 나눠지므로 dp 배열의 크기를 1400 × 10001로 놓고 계산하면 된다. 배열을 채우는 방법은 일반적인 냅색 dp처럼 하면 된다.
발상이 참 신기한 문제. 두고두고 써먹을 수 있을 것 같다.
'Problem Solving > BOJ' 카테고리의 다른 글
17619. 개구리 점프 (0) | 2024.03.22 |
---|---|
1022. 소용돌이 예쁘게 출력하기 (0) | 2024.02.01 |
26607. 시로코와 은행털기 (0) | 2023.07.29 |
2094. 강수량 (0) | 2023.06.14 |
14922. 부분평균 (0) | 2023.05.02 |
Comments