Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

MG

[백준] 2141 - 우체국 본문

컴퓨터과학/알고리즘_PS

[백준] 2141 - 우체국

MG# 2022. 5. 1. 14:55

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

 

2141번: 우체국

첫째 줄에 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 X[1], A[1], X[2], A[2], …, X[N], A[N]이 주어진다. 범위는 |X[i]| ≤ 1,000,000,000, 0 ≤ A[i] ≤ 1,000,000,000 이며 모든 입력은 정수이다.

www.acmicpc.net

처음에 고민을 많이 하다 수학으로 풀었었습니다. 우체국의 위치를 x 로 잡고 각 마을과의 거리와 인구를 곱하면 여러 절댓값으로 이루어진 그래프가 그려지고 그 그래프의 극소점이 답이 되었습니다. 하지만 알고리즘 분류에 그리디가 있는 것을 보고 다른 풀이를 참고하다 더 간단한 방법이 있다는 것을 알게 되었습니다.

 

아래 그림과 같이 어느 위치의 왼쪽의 인구합을 l, 오른쪽을 r로 정의하면 l > r 일때는 왼쪽으로 가면 거리합이 줄고 l < r 일때는 오른쪽으로, l = r 일때는 어느쪽으로 가나 같게 됩니다. 그러면 l = r 인 상황은 인접한 두 마을 중 왼쪽이 답이 되고 l > r or l < r 인 상황은 그 사이에 있는 마을에 우체국이 있어야 최소합이 됩니다. 그렇기에 이 문제는 인구 총합을 구한 후 왼쪽에서부터 더해가면서 그 절반을 넘는 마을이 정답이 됩니다. 그리고 총합이 홀수인 상황도 생각해 (r + 1) / 2 를 비교해줍니다.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

vector<pair<ll, ll>> v;
ll n, a, b, l, r;

int main() {

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a >> b;
        v.emplace_back(a, b);
        r += b;
    }
    sort(v.begin(), v.end());

    for (int i = 0; i < n; i++) {
        l += v[i].second;
        if (l >= (r + 1) / 2) {
            cout << v[i].first << "\n";
            break;
        }
    }

    return 0;
}

'컴퓨터과학 > 알고리즘_PS' 카테고리의 다른 글

[백준] 1629 - 곱셈  (0) 2022.05.04
[백준] 1890 - 점프  (0) 2022.05.02
[백준] 2212 - 센서  (0) 2022.04.30
[백준] 11727 - 2 x n 타일링 2  (0) 2022.04.30
[백준] 11653 - 소인수분해  (0) 2022.04.28