백준 2180 (C++) 소방서의 고민
728x90
SMALL

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

 

2180번: 소방서의 고민

첫째 줄에 화재 발생 건수 n이 주어진다. n은 200,000 이하의 양의 정수이다. 둘째 줄부터 n개의 줄에 각각 한 줄에 한 쌍씩 a와 b가 입력된다. a와 b는 40,000 이하의 음이 아닌 정수이다.

www.acmicpc.net

문제 이해

문제의 입출력을 보자.

입력
3
2 0
1 2
0 3

출력
5

운이 좋게도 주어진 입력 예시 순서를 따라가면 출력이 나온다.
화재를 진압하는데 걸리는 시간은 at + b이므로

1번째 소방서에서 0초 소비, (2 * 0 + 0)

2번째 소방서에선 2초 소비, (1 * 0 + 2)

3번째 소방서에선 3초 소비 (0 * 2 + 3) 하므로

총 5초(정확히는 단위 시간) 이 소비된다.

 

 

 

 

 

수식화

i) a1, b1 ... ai, bi,    ai+1, bi+1 ... an, bn

 최적해를 가정

이때 i번째 소방서에서 ti는 ai, bi 에 관한 1차 함수일 것이고, 그 식은

ai * ti + bi

i+1번째 소방서에서 시간 ti+1은

ti+1 = ti + ai ti + bi
따라서
ti+2 = ti + ai ti + bi + ( ti + ai ti + bi ) ai+1 + bi+1

이다.

 

 

ii) a1, b1 ... ai+1, bi+1,    ai, bi, ... an, bn

최적해가 아닌 다른 해일때

i+1번째 소방서에서 시간 ti+1은

ti+1 = ti + ai+1 ti + bi+1
따라서
ti+2' = ti + ai+1 ti + bi+1 + ( ti + ai+1 ti + bi+1 ) ai + bi

 

여기서 i)의 상황이 최적임을 가정했으므로 ti+2 <= ti+2' 이다.

이 부등식의 동항을 제거, 제거하다보면

 ≤ 

일때 최적해라는 결과를 얻게 된다.

 

 

그리디 알고리즘

   가 최적해이다.

다만, a == 0 인 경우 화재 진압에 항상 b만큼의 시간이 걸린다는 것을 유의하자.

따라서 double b / a의 값이 큰 순서대로 정렬하고 조건에 맞게 총 시간을 더한다.

 

 


 

SMALL

 

728x90

 

 

코드

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long;
const int MAX = 40000;
ll n, sum=0;
vector<tuple<double, int, int>> v;
vector<pair<int, int>> tail;

void print() {
    for (int i = 0; i < n; i++) {
        cout << get<0>(v[i]) << " " << get<1>(v[i]) << " " << get<2>(v[i]) << '\n';
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n;
    for (int i = 0; i < n; i++) {
        double a, b;
        cin >> a >> b;
        if (a == 0) {
            v.push_back(make_tuple(MAX, a, b));
        }
        else v.push_back(make_tuple(b/a, a, b));
    }
    sort(v.begin(), v.end());
   // print();
    
    int t = 0;
    for (int i = 0; i < n; i++) {
        sum += get<1>(v[i]) * t + get<2>(v[i]);
        sum %= 40000;
        t = sum;
    }
    cout << sum;
    return 0;
}

 


 

728x90
LIST

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

백준 1912 (C++) 연속합  (0) 2021.09.29
백준 10423 (C++) 전기가 부족해  (0) 2021.09.29
백준 2581 (C++) 소수  (0) 2021.09.28
백준 1717 (C++) 집합의 표현  (0) 2021.09.28
백준 10984 (C++) 내 학점을 구해줘  (0) 2021.09.26