본문 바로가기
Algorythms

백준 1826번 연료 채우기 c++ 풀이

by 준형코딩 2023. 8. 28.

문제

성경이는 트럭을 정글 속에서 운전하다가 트럭의 연료탱크에 갑자기 구멍이 나서 1km를 가는데 1L의 연료가 새 나가게 되었다. 이것을 고치기 위해서는 가장 가까운 마을에 가야 한다. 그런데 그냥 가다가는 중간에 연료가 다 빠질 수가 있다. 다행스럽게도 정글 곳곳에 연료를 채울 수 있는 주유소가 N개 있다. 그런데 정글 속에서 중간에 차를 멈추는 행위는 매우 위험한 행위이므로 주유소에서 멈추는 횟수를 최소화 하려 한다.

그리고 다행이도 성경이의 트럭은 매우 좋아서 연료 탱크에는 연료의 제한이 없이 많이 충분히 많이 넣을 수 있다고 한다. 각각의 주유소의 위치와, 각 주유소에서 얻을 수 있는 연료의 양이 주어져 있을 때, 주유소에서 멈추는 횟수를 구하는 프로그램을 작성하시오.

정글은 일직선이고, 성경이의 트럭과 주유소도 모두 일직선 위에 있다. 주유소는 모두 성경이의 트럭을 기준으로 오른쪽에 있다.

입력

첫째 줄에 주유소의 개수 N(1 ≤ N ≤ 10,000)가 주어지고 두 번째 줄부터 N+1번째 줄 까지 주유소의 정보가 주어진다. 주유소의 정보는 두개의 정수 a,b로 이루어 져 있는데 a(1 ≤ a ≤ 1,000,000)는 성경이의 시작 위치에서 주유소 까지의 거리, 그리고 b(1 ≤ b ≤ 100)는 그 주유소에서 채울 수 있는 연료의 양을 의미한다. 그리고 N+2번째 줄에는 두 정수 L과 P가 주어지는데 L(1 ≤ L ≤ 1,000,000)은 성경이의 위치에서 마을까지의 거리, P(1 ≤ P ≤ 1,000,000)는 트럭에 원래 있던 연료의 양을 의미한다.

모든 주유소와 마을은 서로 다른 좌표에 있고, 마을은 모든 주유소보다 오른쪽에 있다.

출력

첫째 줄에 주유소에서 멈추는 횟수를 출력한다. 만약 마을에 도착하지 못할경우 -1을 출력한다.

예제 입력 1 복사

4
4 4
5 2
11 5
15 10
25 10

예제 출력 1 복사

3

 

그리디, 우선순위 큐 문제이다.

 

우선순위 큐를 이용하여 각 주유소마다 내가 가진 연료로 갈 수 있는 주유소를 우선순위 큐에 넣어주고 만약에 그 우선순위 큐의 들어있는 값들 중 가장 큰 주유소에 도착했을 때 마다 충전을 하는 방식을 선택했고 로직적으로 흠이 없다고 생각했으나 정답 처리를 받지 못했고 다른 풀이를 참고하게 되었다.

 

다른 풀이들도 로직은 나의 풀이와 거의 유사했다. 하지만 나는 모든 주유소에 멈춰서 연산을 한 반면 다른 풀이들은 연료가 고갈될 때 까지 달린 후 그 동안 쌓인 PQ에 들어있는 주유소의 연료 값으로 충전을 하고 만약에 모든 PQ값을 소모 했는데도 목적지에 도착할 수 없다면 -1 아니라면 정답을 출력해 주었다. 어떻게 이런 풀이들을 생각해 내는건지 참 대단하다

 

틀린 풀이

- c++ 

#include <bits/stdc++.h>
using namespace std;




int main(void){

    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    vector<pair<int,int>>v;

    for(int i = 0 ; i < n; i++){
        int a,b;
        cin >> a >> b;
        v.push_back({a,b});
    }

    int nowDis=0;
    int nowOil=0;
    int end=0;

    int ans = 0;

    cin >> end  >> nowOil;

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

    priority_queue<pair<int,int>>pq;
    pq.push({v[0].second,v[0].first});

    for(int i = 0 ; i < v.size(); i++){


        int twoDis = v[i].first-nowDis;
        nowDis += twoDis;
        nowOil -= twoDis;
//        cout << "nowDis : " << nowDis << " / nowOil : " << nowOil <<  "\n";

        for(int j = i ; j < v.size(); j++ ){
            if(v[j].first - nowDis <= nowOil){
                pq.push({v[j].second,v[j].first});
//                cout << v[j].first << " " << v[j].second << "\n";
            }
        }

//        cout << "top / " << pq.top().second << " " << pq.top().first << "\n";

        if(v[i].first == pq.top().second && v[i].second == pq.top().first && nowDis < end && (end-nowDis) - nowOil > 0 ){
            nowOil += v[i].second;
            pq.pop();
//            cout << nowOil << " / pop!!" <<"\n";
            ans ++;
        }else{
//            cout << "continue!!" <<"\n";
            continue;
        }

//        cout << nowDis << "\n";
    }
//    cout << nowOil << "\n";


    if(nowDis+nowOil >= end){
        cout << ans << "\n";
    }else{
        cout << -1;
    }













    return 0;
}

 

 

 

정답 풀이

- c++

 

#include <bits/stdc++.h>
using namespace std;


int info[1000001];

int main(void){

    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    vector<pair<int,int>>v;

    for(int i = 0 ; i < n; i++){
        int a,b;
        cin >> a >> b;
        v.push_back({a,b});
        info[a]=b;
    }

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

    int L,P;
    cin >> L >> P;

    priority_queue<int>pq;

    int nowOil=P;
    int ans =0;

    for(int i = 1 ; i < L; i++){
        nowOil--;
        if(info[i])pq.push(info[i]);

        if(!nowOil){

            if(pq.empty()){
                cout << -1;
                return 0;
            }else{
                ans++;
                nowOil+=pq.top();
                pq.pop();

            }
        }
    }
    cout << ans << "\n";




    return 0;
}