프로그래머스 - 주차 요금 계산 (Lv.2)

3 minute read

문제 링크

문제 접근

  • 문자열 파싱은 stringstream 을 활용한다.
    • » 연산자는 공백문자를 만날 떄까지 버퍼의 문자를 읽어들이고, 공백문자는 버퍼에 남겨둔다.
    • get() 함수는 공백문자를 포함한 문자 하나를 버퍼에서 읽어온다.
  • 들어온 차량에 대한 데이터를 담는 배열(inArr)과 나가는 차량에 대한 데이터를 담는 배열(outArr)을 선언하여, 입/출차 기록에 따라 차량 번호와 시간을 분 단위로 계산하여 담는다.
  • 차량의 누적시간을 담는 자료구조로 map 자료구조를 활용한다.
    • inArr 배열과 outArr 배열 모두 중복된 차량 번호가 있을 수 있다. inArroutArr 을 앞에서부터 탐색하며 비교하면서 방문표시를 남기며 누적 시간을 계산한다.
    • 출차 기록이 없는 차량은 inVisited 배열에서 false 로 표시되어 있으므로, 해당 차량은 23시 59분을 출차 시간으로 간주하여 계산을 추가한다.

구현(All Pass)

#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <map>

using namespace std;

map<int, int> updateTotalTime(vector<pair<int, int>>& inArr, vector<pair<int, int>>& outArr){
    map<int, int> ret;
    vector<bool> outVisited(outArr.size(), false);
    vector<bool> inVisited(inArr.size(), false);
    
    int carNum;
    for(int i=0; i<inArr.size(); i++){
        carNum = inArr[i].first;
        for(int j=0; j<outArr.size(); j++){
            if(carNum==outArr[j].first && outVisited[j]==false){
                inVisited[i] = true;
                outVisited[j]=true;
                if(ret.find(carNum)==ret.end())
                    ret[carNum] = outArr[j].second - inArr[i].second;
                else
                    ret[carNum] += (outArr[j].second - inArr[i].second);
                break;
            }
        }
    }
    
    // 나가지 못한 차량 시간 계산
    int endTime = 23*60 + 59;
    for(int i=0; i<inVisited.size(); i++){
        if(inVisited[i]==false){
            carNum = inArr[i].first;
            // cout << "car num: " << carNum << ", " << "cur time: " << inArr[i].second << endl;
            if(ret.find(carNum)==ret.end())
                ret[carNum] = endTime - inArr[i].second;
            else
                ret[carNum] += (endTime - inArr[i].second);
        }
    }
    
    return ret;
}

vector<int> solution(vector<int> fees, vector<string> records) {
    vector<int> answer;
    vector<pair<int, int>> inArr, outArr;
    // parsing
    string state, time, hour, min, scarNum;
    int carNum;
    stringstream ss;
    for(int i=0; i<records.size(); i++){
        ss.clear();
        ss.str(records[i]);
        ss >> time >> scarNum >> state;
        hour.push_back(time[0]), hour.push_back(time[1]);
        min.push_back(time[3]), min.push_back(time[4]);
        int tMin = stoi(hour)*60 + stoi(min);
        hour.clear(); min.clear();
        carNum = stoi(scarNum);
        if(state=="IN"){
            inArr.push_back(make_pair(carNum, tMin));
        }
        else if(state=="OUT"){
            outArr.push_back(make_pair(carNum, tMin));
        }
    }
    
    map<int, int> carTime = updateTotalTime(inArr, outArr);
    int parkingTime, totalFee;
    bool alpha;
    for(auto ele:carTime){
        // cout << "car num: " << ele.first << ", " << ele.second << endl;
        parkingTime = ele.second;
        if(parkingTime < fees[0]) // 기본 시간보다 작은 경우 기본 요금 청구
            answer.push_back(fees[1]);
        else{
            alpha = (parkingTime - fees[0]) % fees[2];
            totalFee = fees[1] + ((parkingTime - fees[0])/fees[2] + alpha) * fees[3];
            answer.push_back(totalFee);
        }
    }

    return answer;
}
  • stringstream 은 str() 메소드를 활용하여 버퍼를 채울 수 있다.
    • ss.str(records[i]);

구현2

#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <sstream>

using namespace std;

map<string, int> table;

int getMinutes(string time){
    int ret = 0;
    stringstream stm(time);
    string hour, minute;
    getline(stm, hour, ':');
    stm >> minute;
    
    ret = stoi(hour) * 60 + stoi(minute);
    return ret;
}

void updateTable(vector<string>& records)
{
    map<string, int> enterInfo; // 차량이 들어온 시간 정보
    for(int i=0; i<records.size(); i++){
        stringstream stm(records[i]);
        string time, carNumber, status;
        stm >> time >> carNumber >> status;
        if (status == "IN") {
            enterInfo[carNumber] = getMinutes(time);
        }
        else if (status == "OUT") {
            table[carNumber] += (getMinutes(time) - enterInfo[carNumber]);
            enterInfo[carNumber] = -1; // 주차장을 빠져 나간 경우
        }
    }
    
    // 출차된 내역이 없는 경우
    for (auto ele : enterInfo) {
        if (ele.second != -1) {
            table[ele.first] += (getMinutes("23:59") - ele.second);
        }
    }
    
}

bool cmp(pair<string, int> p1, pair<string, int> p2)
{
    return p1.first < p2.first;
}

int getExtraFee(int exceedTime, int unitTime, int unitFee)
{
    if (exceedTime % unitTime != 0) return (exceedTime / unitTime + 1) * unitFee;
    return (exceedTime / unitTime) * unitFee;
}

void calculateParkingFee(vector<int>& fees, vector<int>& answer)
{
    map<string, int> feeInfo;
    int defaultTime = fees[0];
    int defaultFee = fees[1];
    int unitTime = fees[2];
    int unitFee = fees[3];
    
    for (auto ele : table) {
        if (ele.second <= defaultTime) feeInfo[ele.first] = defaultFee;
        else if (ele.second > defaultTime) {
            feeInfo[ele.first] = defaultFee + getExtraFee(ele.second - defaultTime, unitTime, unitFee);
        }
    }
    vector<pair<string, int>> tmp(feeInfo.begin(), feeInfo.end());
    sort(tmp.begin(), tmp.end(), cmp);
    
    for(auto ele : tmp){
        answer.push_back(ele.second);
    }
}

vector<int> solution(vector<int> fees, vector<string> records) {
    vector<int> answer;
    updateTable(records);
    calculateParkingFee(fees, answer);
    return answer;
}

Leave a comment