본문 바로가기

Coding Test

백준 10427 빚

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

#include <iostream>
#include <vector>
#include <algorithm>

#define INF 987654321

using namespace std;


int main() {

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

    int t;
    cin >> t;

    for (int test = 0; test < t; test++) {

        int n;
        long long ans = 0;
        cin >> n;

        vector<long long> arr(n+1);
        vector<long long> prefix(n+1);


        for (int i = 1; i <= n; i++) {
            cin >> arr[i];
        }

        sort(arr.begin(), arr.end());

        for (int i = 1; i <= n; i++) {

            prefix[i] = prefix[i - 1] + arr[i];

        }



        for (int i = 1; i <= n; i++) {           //가장 많이 빌린 돈
            long long temp = INF;
            for (int j = i; j <= n; j++) {
                //가장 많은 돈을 빌렸을 때 빌린 돈*M-빌린 돈의 합=이자
                temp = min(temp, arr[j] * i - prefix[j] + prefix[j - i]);
            }

            ans += temp;
        }

        cout << ans << "\n";


    }

    return 0;
}

 

  그리디+누적 합 문제이다.

 (추가로 갚아야 할 돈)=(가장 많이 빌린 돈)*(빚을 갚는 횟수)-(빌린 돈의 합) 즉, 배열의 부분합이 필요하므록 누적 합을 사용한다.

 

 풀이

        for (int i = 1; i <= n; i++) {
            cin >> arr[i];
        }

        sort(arr.begin(), arr.end());

        for (int i = 1; i <= n; i++) {

            prefix[i] = prefix[i - 1] + arr[i];

        }

 

 우선 배열을 입력받고 정렬한 후 부분합을 구한다. 추가로 갚아야 할 돈이 최소가 되려면 가장 많이 빌린 돈과 빌린 돈의 합이 최소가 되어야 하기 때문에 배열을 정렬한 후 연산한다.

 

        for (int i = 1; i <= n; i++) {           
            long long temp = INF;
            for (int j = i; j <= n; j++) {
                //가장 많은 돈을 빌렸을 때 빌린 돈*M-빌린 돈의 합=이자
                temp = min(temp, arr[j] * i - prefix[j] + prefix[j - i]);
            }

            ans += temp;
        }

  이후 i부터 j 까지의 돈을 빌렸을 때의 이자를 모두 구하여 최솟값을 추린다. 이를 ans에 더하여 그 값을 출력하면 답을 구할 수 있다.

'Coding Test' 카테고리의 다른 글

백준 1654 랜선 자르기  (0) 2024.05.27
백준 15663 N과 M(9)  (0) 2024.05.26
백준 2473 세 용액  (0) 2024.05.24
백준 16926 배열 돌리기 1  (0) 2024.05.23
백준 15961 회전 초밥  (0) 2024.05.22