알고리즘/BOJ

백준 2513번 : 통학버스 (C++)

DOWN 2021. 12. 6. 19:39

문제: https://www.acmicpc.net/problem/2513

 

2513번: 통학버스

첫째 줄에는 세 개의 양의 정수 N, K, S가 빈칸을 사이에 두고 순서대로 주어진다. 첫 번째 정수 N은 아파트 단지의 수이며 2 ≤ N ≤ 30,000이다. 두 번째 정수 K는 1 ≤ K ≤ 2,000이며, 통학버스의 정원

www.acmicpc.net

 

 

수용 한계량이 있는 통학버스가 존재할 때, 모든 학생을 태울 수 있는 최소거리를 찾는 문제입니다.
생각을 해보면 모든 학생을 태워야 하므로 멀리 있는 학생 위치도 결국엔 한 번 이상은 지나야 합니다. 그래서 멀리 있는 학생들부터 태워서 오는 길에 수용량이 남으면 태우는 방법으로 하면 최소거리를 구할 수 있는 그리디 문제입니다.

 

통학버스의 시작 위치를 s라 하면 s의 왼쪽에 존재하는 학생과 오른쪽에 존재하는 학생들을 서로 다른 vector에 집어넣고 멀리 있는 학생들부터 처리할 수 있도록 sort를 해줍니다. 그리고 while loop을 돌면서 해당 vector가 빈 vector가 되도록 로직을 실행하게 하면 쉽게 구현 가능한 문제입니다.

 

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

using namespace std;


int caculateDistance(vector<pair<int, int>> & Students, int k, int s){
    int nowPos, nowNum, ans;

    nowPos = s;
    nowNum = 0;
    ans = 0;
    
    while(!Students.empty()){
        int pos = Students.back().first;
        int num = Students.back().second;
        
        if(num + nowNum <= k){
            Students.pop_back();
            nowNum += num;
        }
        else{
            Students.back().second -= k - nowNum;
            nowNum += k - nowNum;
        }

        ans += abs(nowPos - pos);
        nowPos = pos;

        if(nowNum == k || Students.empty()){
            ans += abs(nowPos - s);
            nowPos = s;
            nowNum = 0;
        }
    }

    return ans;
}

int main(){

    int n, k, s;
    cin >> n >> k >> s;
    
    vector<pair<int, int>> leftStudents, rightStudents;

    for(int i=0; i<n; i++){
        int pos, num;
        cin >> pos >> num;
        if(pos < s){
            leftStudents.push_back(make_pair(pos, num));
        }
        else if(pos > s){
            rightStudents.push_back(make_pair(pos, num));
        }
    }

    sort(leftStudents.begin(), leftStudents.end(), greater<>());
    sort(rightStudents.begin(), rightStudents.end(), less<>());

    cout << caculateDistance(leftStudents, k, s) + caculateDistance(rightStudents, k , s);

    return 0;
}