넘치게 채우기

[BOJ] 2786 - 상근이의 레스토랑 본문

PS/BOJ

[BOJ] 2786 - 상근이의 레스토랑

riveroverflow 2025. 3. 29. 00:45
728x90
반응형

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

BOJ - 상근이의 레스토랑

문제 유형: 정렬, 그리디

문제 난이도: Gold I

시간 제한: 2초

메모리 제한: 256MB

 

문제

상근이는 도서관에서 번 돈으로 서강대 곤자가 플라자에 레스토랑을 하나 열었다. 이 레스토랑에는 음식을 N종류 팔고 있고, 손님은 서로 다른 음식을 여러개 시킬 수 있다. 이때, 음식을 시키는 순서가 중요하다. 그 이유는 각 음식을 첫 번째로 시킬 때의 가격과 아닐 때의 가격이 다르기 때문이다. 즉, 모든 음식 i의 가격은 첫 번째로 시킬 때의 가격 Ai와 아닐 때의 가격 Bi 두가지가 있다.

배가 고픈 창영이는 상근이네 레스토랑에서 음식을 시켜먹으려고 한다. 이때, 1개, 2개, ..., N개 시킬 때 필요한 최소 가격을 각각 구하는 프로그램을 작성하시오. 같은 종류 음식을 여러 번 중복해서 주문할 수 없다.

 

입력

첫째 줄에 상근이네 레스토랑의 음식의 개수 N(2 ≤ N ≤ 500,000)이 주어진다. 다음 N개의 줄에는 각 음식의 가격 Ai와 Bi가 주어진다. (0 ≤ Ai, Bi ≤ 1,000,000,000)

 

출력

출력은 총 N개로 이루어져 있다. i번째 줄에는 음식을 i개 시킬 때 필요한 최소 가격을 출력한다.

 

풀이

처음에는 유니온 파인드로 가장 작은 A를 관리하면서 그리디하게 풀었는데, 이는 방법이 아니였다.

 

풀이 참조:https://peisea0830.tistory.com/115

 

[Python 3] BOJ - 2786 "상근이의 레스토랑"

# 문제 링크 https://www.acmicpc.net/problem/2786 2786번: 상근이의 레스토랑 첫째 줄에 상근이네 레스토랑의 음식의 개수 N(2 ≤ N ≤ 500,000)이 주어진다. 다음 N개의 줄에는 각 음식의 가격 Ai와 Bi가 주어진

peisea0830.tistory.com

 

<A, B>그대로 배열에 담아서 B를 기준으로 오름차순 정렬한다.

suff_mins[i]에는 i ~ n-1까지의 최소값을 담을 것이다.

 

두 가지 케이스가 있기 때문이다:

1. 저렴한 B들 k-1개를 고르고 가장 싼 A 1개를 [k-1, n-1]범위 에서 구하기 - suff_mins를 이용하면 간단하게 구할 수 있다.

 

2. k개 그대로 구했다가, A로 바꿨을 때 가장 낮아지는 것을 구하기 - (A - B)를 담은 최소 힙의 꼭대기를 통해서 뭘 가장 먼저 주문하는게 이득인지 알 수 있다.

 

정답 배열에 매우 큰 값으로 초기화해준 다음, 1번케이스와 2번케이스별로 정답배열의 최소값을 갱신시키면 된다.

 

코드

C++

#include <bits/stdc++.h>

#include <climits>

using namespace std;
using pii = pair<int, int>;
using ll = long long;

int n;

int main(int argc, char *argv[]) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;

    vector<pii> arr;
    for (int i = 0; i < n; i++) {
        int a, b;
        cin >> a >> b;
        arr.emplace_back(a, b);
    }
    sort(arr.begin(), arr.end(), [](const auto &a, const auto &b) {
        if (a.second == b.second) return a.first < b.first;
        return a.second < b.second;
    });

    vector<int> suff_mins(n);
    suff_mins[n - 1] = arr[n - 1].first;
    for (int i = n - 2; i >= 0; i--) {
        suff_mins[i] = min(suff_mins[i + 1], arr[i].first);
    }

    ll sum = 0;
    vector<ll> ans(n, LLONG_MAX);
    for (int i = 0; i < n; i++) {
        ans[i] = min(ans[i], sum + suff_mins[i]);
        sum += arr[i].second;
    }

    priority_queue<int, vector<int>, greater<>> pq;
    sum = 0;
    for (int i = 0; i < n; i++) {
        sum += arr[i].second;
        pq.push(arr[i].first - arr[i].second);
        ans[i] = min(ans[i], sum + pq.top());
    }

    for (const auto &elem : ans) cout << elem << "\n";

    return 0;
}
728x90
반응형

'PS > BOJ' 카테고리의 다른 글

[BOJ] 23300 - 웹 브라우저 2  (0) 2025.03.30
[BOJ] 28464 - Potato  (0) 2025.03.29
[BOJ] 1926 - 그림  (0) 2025.03.27
[BOJ] 5014 - 스타트링크  (0) 2025.03.27
[BOJ] 2573 - 빙산  (0) 2025.03.26