이번 포스팅에서는 백준 온라인 저지의 1214번 문제 쿨한 물건 구매를 다루어 보겠습니다. 이 문제는 제한된 종류의 지폐를 사용하여 특정 금액 이상의 최소 지불 금액을 구하는 문제로, 효율적인 알고리즘 설계와 수학적 사고가 필요한 흥미로운 문제입니다.
문제를 해결하면서 최적화 기법과 수학적 아이디어를 활용하여 시간 복잡도를 줄이는 방법에 대해 알아보겠습니다.
문제 : https://www.acmicpc.net/problem/1214
문제 설명
구사과는 지폐를 오직 두 종류만 가지고 있습니다. 바로 P원 지폐와 Q원 지폐입니다. 이 두 종류의 지폐를 구사과는 무한히 많이 가지고 있습니다.
오늘 구사과가 구매하려고 하는 물건의 가격은 D원입니다. 구사과가 이 물건을 구매하기 위해서 지불해야 하는 금액의 최솟값은 얼마일까요?
물건을 구매하기 위해서는 물건의 가격보다 크거나 같은 금액을 지불해야 합니다.
즉, 구사과는 P원 지폐와 Q원 지폐를 조합하여 D원 이상이 되는 최소의 금액을 만들어야 합니다. 이때, 각 지폐의 개수는 제한이 없으므로, 가능한 모든 조합 중에서 지불해야 하는 금액의 최솟값을 구하는 것이 문제의 목표입니다.
입력
첫째 줄에 D, P, Q가 주어집니다. 모두 \(10^9\)보다 작거나 같은 자연수입니다.
출력
첫째 줄에 물건을 구매하기 위해 구사과가 지불해야 하는 금액의 최솟값을 출력합니다.
예제 입력 1
| |
예제 출력 1
| |
20 = 7 × 1 + 13 × 1
예제 입력 2
| |
예제 출력 2
| |
21 = 7 × 3 + 13 × 0
예제 입력 3
| |
예제 출력 3
| |
18 = 7 × 0 + 9 × 2
예제 입력 4
| |
예제 출력 4
| |
43 = 9 × 1 + 17 × 2
접근 방식
이 문제는 두 종류의 지폐를 사용하여 원하는 금액 D 이상을 만들 수 있는 최소 금액을 찾는 문제입니다. 하지만 D, P, Q의 범위가 최대 \(10^9\)이기 때문에 모든 가능한 지폐 조합을 탐색하는 것은 시간 초과의 원인이 됩니다.
주요 아이디어
반복 횟수 제한
지폐의 사용 횟수를 D를 Q로 나눈 몫 근처로 제한하여, 탐색 범위를 좁힙니다. 최적의 조합은 이 근처에서 발생할 가능성이 높기 때문입니다.
두 지폐의 역할을 바꾸어 탐색
P와 Q의 역할을 바꾸어 두 번의 탐색을 수행하여 모든 경우의 수를 고려합니다.
조기 종료 조건
현재 계산된 금액이 이미 최소 금액보다 크거나 같다면 더 이상의 탐색을 중단하여 불필요한 계산을 줄입니다.
C++ 코드와 설명
| |
코드의 동작 단계별 설명
함수
check정의D: 물건의 가격P,Q: 두 종류의 지폐ans: 현재까지의 최소 지불 금액
1void check(ll D, ll P, ll Q, ll &ans)반복 범위 설정
1 2ll y_start = max(0LL, D / Q - 1000000); ll y_end = D / Q + 1000000;y_start:D / Q - 1,000,000(0 이상)y_end:D / Q + 1,000,000
메인 루프
1 2 3 4 5 6 7 8 9 10 11 12 13for (ll y = y_start; y <= y_end; ++y) { ll total_Q = y * Q; if (total_Q >= ans) break; if (total_Q >= D) { ans = min(ans, total_Q); break; } ll rem = D - total_Q; ll x = (rem + P - 1) / P; ll total_amount = total_Q + x * P; if (total_amount >= ans) continue; ans = total_amount; }total_Q: Q 지폐로 지불한 금액rem: 남은 금액x: 필요한 P 지폐의 개수total_amount: 총 지불 금액
메인 함수에서의 호출
1 2check(D, P, Q, ans); check(D, Q, P, ans);
C++ without library 코드와 설명
| |
코드의 동작 단계별 설명
입력 처리
1scanf("%lld %lld %lld", &D, &P, &Q);초기 최소 금액 설정
1ll ans = ((D + P - 1) / P) * P;함수 호출 및 최소 금액 갱신
1 2check(D, P, Q, &ans); check(D, Q, P, &ans);함수
check내부 동작y_start와y_end를 설정하여 반복 범위를 제한- 조기 종료 조건을 활용하여 불필요한 계산을 줄임
결과 출력
1printf("%lld\n", ans);
Python 코드와 설명
| |
코드의 동작 단계별 설명
입력 처리
1 2 3 4D_str, P_str, Q_str = sys.stdin.readline().split() D = int(D_str) P = int(P_str) Q = int(Q_str)초기 최소 금액 설정
1ans = ((D + P - 1) // P) * P함수
check정의 및 호출1 2 3 4 5def check(D, P, Q, ans): # 반복 범위 설정 및 최소 금액 갱신 ans = check(D, P, Q, ans) ans = check(D, Q, P, ans)결과 출력
1print(min_total_amount(D, P, Q))
결론
이번 문제를 통해 제한된 종류의 지폐로 특정 금액 이상의 최소 지불 금액을 구하는 방법에 대해 알아보았습니다. 반복문의 범위를 적절히 제한하고 조기 종료 조건을 활용하여 시간 초과 문제를 해결할 수 있었습니다.
알고리즘 문제를 풀 때는 입력 범위와 시간 복잡도를 고려하여 최적화하는 것이 중요합니다. 이러한 접근 방식을 통해 복잡한 문제도 효율적으로 해결할 수 있습니다.
![Featured image of post [Algorithm] C++/Python 백준 1214번 : 쿨한 물건 구매](/post/algorithm/2024-10-16-boj-1214/tmp_wordcloud_hu_fe1c578ceea9c7b3.png)
![[Algorithm] C++ 백준 1027번 : 이동](/post/algorithm/2024-05-15-boj-1067/tmp_wordcloud_hu_d2763a2586832bca.png)
![[Algorithm] C++/Python 백준 10999번 : 구간 합 구하기 2](/post/algorithm/2024-12-31-boj-10999/index_hu_35a088294bee6df1.png)
![[Algorithm] C++/Python 백준 1214번 : 쿨한 물건 구매](/post/algorithm/2024-10-16-boj-1214/tmp_wordcloud_hu_f0e7cd33e575716.png)
![[Algorithm] C++/Python 백준 15995번 : 잉여역수 구하기](/post/algorithm/2024-10-17-boj-15995/tmp_wordcloud_hu_144fe10175f84e7c.png)
![[Algorithm] C++/Python 백준 27161번 : 크레이지 타임](/post/algorithm/2024-10-17-boj-27161/tmp_wordcloud_hu_b5f4f1ea448e32dd.png)
![[Algorithm] BOJ 13926 gcd(n, k) = 1 — φ(n) 계산 (C++/Python)](/post/algorithm/2025-10-14-boj-13926-gcd-n-k-equals-1-cpp-python-solution/wordcloud_hu_4f80697d0be61606.png)
![[Algorithm] C++ 백준 1031번: 스타 대결](/post/algorithm/2025-10-14-boj-1031-star-battle-cpp-solution/wordcloud_hu_f77f5f84ec32b33a.png)
![[Algorithm] C++ 백준 22289번: 큰 수 곱셈 (3)](/post/algorithm/2025-10-14-boj-22289-big-integer-multiplication-cpp-solution/wordcloud_hu_58aa21e0c6a28f67.png)
![[Algorithm] C++ 백준 5051번: 피타고라스의 정리 (mod n)](/post/algorithm/2025-10-14-boj-5051-pythagorean-mod-n-cpp-solution/wordcloud_hu_7e8a5079e9226a49.png)
![[Algorithm] C++ 백준 8464번: Non-Squarefree Numbers](/post/algorithm/2025-10-14-boj-8464-non-squarefree-numbers-cpp-solution/wordcloud_hu_4f80697d0be61606.png)