티스토리 뷰

Algorithm

[백준 18320] Loan Repayment

devbelly 2021. 4. 28. 17:44

문제

www.acmicpc.net/problem/18320

 

알고리즘

이분탐색

 

풀이

갚을 금액, 기한, 하루에 최소 갚을 금액이 주어졌을 때, 조건을 충족하는 X를 구하는 문제입니다.

 

문제를 풀기 위한 첫 번째 단계는 X를 결정해야하는 것입니다. 결정문제는 이분탐색으로 바꿀 수 있습니다. 이 문제가 어려운 이유는 X를 결정했을 때, 그대로 시뮬레이션하여 K일 이내에 돈을 갚을 수 있는지 계산하게 되면 시간초과가 발생하기 때문입니다.

 

이유는 N제한이 1012이기 때문입니다. X를 결정하는 시간복잡도는 O(logN)에 해당하는데 그대로 시뮬레이션 하게 되면 X마다 선형시간이 요구되기 때문입니다.

 

한가지 할 수 있는 관찰 중 하나는 John이 갚아나가는 금액은 비오름차순의 형태를 띤다는 것입니다. 이를 이용해 하루에 갚아나가야 하는 금액이 A라면 남은 돈에서 A,A,A... 처럼 하나씩 빼지말고 계산을 통해 A를 몇개 빼야할지 계산하면 됩니다.

 

이를 계산하기 위해선 하루에 갚아야 하는 금액 A에서 X를 곱하면 A를 내야하는 경계선 금액(남은 돈)이 나오게 됩니다. 이 값을 leftMost라는 변수를 통해 나타냈습니다. 위 문단에서 '몇개'를 계산하는 것은 (rest - leftMost + givePerday) / givePerday; 통해 가능합니다.  givePerday를 더하는 이유는 올림을 계산하기 위함입니다. 마지막으로 최적화를 위해 solve()함수 내에서 dayK를 넘거나 남은 금액이 0 이하가 되면 while문을 종료하도록 했습니다.

 

코드

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; ++i)
#define REP(i, n) for (int i = 1; i <= n; ++i)
using namespace std;

#define int long long
int N, K, M;

bool solve(int m) {
    int rest = N;
    int day = 0;
    while (1) {
        int givePerday = rest / m;
        if (givePerday <= M) {
            int ret = day + (rest + M-1) / M;
            return ret<=K;
        }
        int leftMost = givePerday * m;
        int dayCnt = (rest - leftMost + givePerday) / givePerday;

        day += dayCnt;
        if (day > K) return false;
        int give = dayCnt * givePerday;
        rest -= give;
        if (rest <= 0) {
            break;
        }
    }

    return day <= K;
}

signed main() {
    cin.tie(NULL);
    cout.tie(NULL);
    ios::sync_with_stdio(false);

    cin >> N >> K >> M;

     int lo = 1;
     int hi = N;
     int best = -1;
     while (lo <= hi) {
         int mid = (lo + hi) / 2;
         if (solve(mid)) {
             best = mid;
             lo = mid + 1;
         } else {
             hi = mid - 1;
         }
     }
     cout << best;
    return 0;
}

 

'Algorithm' 카테고리의 다른 글

[백준 3015] 오아시스 재결합  (0) 2021.05.05
[백준 20971] No Time to Paint  (0) 2021.04.30
[백준 9376] 탈옥  (0) 2021.04.25
[백준 2398] 3인 통화  (0) 2021.04.24
[백준 4716] 풍선  (0) 2021.04.15
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
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
글 보관함