📕문제
https://school.programmers.co.kr/learn/courses/30/lessons/92341#
💡문제 요점
입차시간과 출차시간을 비교해서 계속해서 누적 주차시간을 더해줘서 결과적으로는 차량별로 주차요금을 계산하는 문제입니다.
여기서 중요한 점은 바로 차량번호를 오름차순으로 정렬해서 주차요금을 계산해줘야 합니다.
🔎문제 풀이
- 우선 차량은 입차와 출차. 두 가지 경우의 수가 있습니다.
- A가 입차를 했을 경우, 다시 A가 들어왔다면 출차인 경우입니다.
- A가 입차를 했는데, 만약 A가 다시 들어오지 않는다면 23:59 자동 출차 처리해줘야 합니다.
- 문제에서 중요한 점은 출차할 때마다 요금을 계산하는 것이 아닌, 출차할때마다 누적 주차시간을 더해줘서 최종적으로 요금을 청구하는 것입니다.
- 저는 두 가지의 map을 통해서 차량을 관리했습니다.
- 첫 번째 map은 (차량번호, 출차/입차 시간) -> A
- 두 번째 map은 (차량번호, 누적 주차시간의 합) -> B
- map을 쓴 이유는 key를 자동적으로 오름차순으로 정렬하기 때문에, 나중에 차량번호를 오름차순으로
정렬해 줘 야하기 때문에 map을 쓰겠다고 판단했습니다. - 만약 차량번호가 A에 없다면, 그 차량번호는 입차인 경우입니다.
- 입차인 경우는 차량번호와 입차 시간을 A에 삽입합니다.
- 만약 차량번호가 A에 있다면 그 차량번호는 출차인 경우입니다.
- 출차인 경우, 해당 출차시간 - 차량번호에 해당하는 value(입차시간)을 뺀 값을 B에 삽입합니다.
- B에 삽입할 때도, 비어있는지, 아닌지를 판단해서 누적합을 더해줘야 합니다.
- 모든 records만큼 반복문을 돈 뒤 A를 한 번 더 검사합니다.
- 만약 A의 크기가 0이라면 모든 차량은 입차->출차의 과정을 마친 상태입니다.
- 하지만 크기가 0이 아니라면 어떠한 차량은 입차만 했고, 출차를 하지 않은 상태라는 뜻입니다.
- 따라서 그때의 입차시간과 23:59분의 차이를 B에 삽입해 줍니다.
- 주차요금 계산은 간단합니다.
- 만약 누적 주차시간이 기본시간이하라면, 기본요금을 부과합니다.
- 만약 누적 주차시간이 기본시간초과라면, 기본요금 + (누적 주차시간-기본 주차시간)/단위 시간 * 단위 요금을 부과합니다.
- 여기서 체크해야 될 점은 단위시간으로 나눈 초과시간이 나누어 떨어지지 않는다면 올림처리해줘야 합니다.
- 저는 여기서 ceil(올림)을 사용했습니다.
- 여기서 체크해야 될 점은 단위시간으로 나눈 초과시간이 나누어 떨어지지 않는다면 올림처리해줘야 합니다.
❌주의해야 할 점
- 누적 주차시간을 통해서 주차요금을 부과해라.
- 단위시간으로 나눈 초과시간을 올림 처리해서 요금을 부과해야 한다.
💻소스 코드
#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
#include <map>
using namespace std;
map<string,string>m;
map<string,int>cc;
vector<pair<string,int> >ans;
int first_t=0,second_t=0;
string get_time(vector<string> records, int step){ //HH:MM인 형식을 HHMM으로 반환하는 함수.
string temp="";
for(int i=0; i<=4; i++){
if(i==2)
continue;
temp+=records[step][i];
}
return temp;
}
string get_number(vector<string> records,int step){ //차 번호를 반환하는 함수.
string temp="";
for(int i=6; i<=9;i++){
temp+=records[step][i];
}
return temp;
}
void funct_time(string first, string second) //출차시간-입차시간을 반환하는 함수.
{
first_t=0,second_t=0;
first_t=(first[0]-'0')*600+(first[1]-'0')*60+(first[2]-'0')*10+(first[3]-'0');
second_t = (second[0]-'0')*600+(second[1]-'0')*60+(second[2]-'0')*10+(second[3]-'0');
return;
}
vector<int> solution(vector<int> fees, vector<string> records) {
vector<int> answer;
for(int i=0; i<records.size();i++){
string c="",t="";
c=get_number(records,i);
t=get_time(records,i);
if(m.find(c)==m.end()){ //map없다면 처음 입차이기 때문에, 그때의 차 넘버와 들어온 시간을 map에 넣어줌.
m.insert(make_pair(c,t));
}
else //이미 map에 들어와있는 차번호라면 출차이기 때문에
{
string tt = m.find(c)->second; //입차한 시간
funct_time(tt,t); //출차한 시간 - 입차한 시간을 분단위로 전환함.
if(cc.find(c)==cc.end()){ //처음으로 출차한 경우는 주차시간을 더해줌.
cc.insert(make_pair(c,second_t-first_t));
}
else{ //처음으로 출차한 경우가 아니라면 누적 주차시간을 넣어줌.
int total = cc.find(c)->second+second_t-first_t;
cc[c]=total; //누적 주차시간 업데이트
}
m.erase(c); //출차한 경우 맵에서 차 번호를 지워줌.
}
}
for(auto iter=m.begin(); iter!=m.end();iter++){ //만약 입차를 했는데, 출차를 안한 경우를 전부다 처리해줌.
funct_time(iter->second,"2359"); //입차하고 출차안한경우는 23:59출차로 생각하기 때문에
if(cc.find(iter->first)!=cc.end())
cc[iter->first]=cc.find(iter->first)->second+second_t-first_t;
else
cc.insert(make_pair(iter->first,second_t-first_t));
}
for(auto iter= cc.begin(); iter!=cc.end();iter++){
if(iter->second<=fees[0]){ //기본시간이하로 주차햇다면 그냥 기본요금을 넣어줌.
answer.push_back(fees[1]);
}
else{ //기본시간 초과라면 초과한 단위시간만큼 추가요금을 부과함.
int cost=0;
cost = fees[1]+ceil(double(iter->second-fees[0])/fees[2])*fees[3]; //
answer.push_back(cost);
}
}
return answer;
}
자세한 코드설명은 주석을 통해서 이해해 주시면 감사하겠습니다.
😃느낀 점
- 문제를 풀다 보니 문자열 다루는 게 굉장히 낯설어서 많이 고생을 했다.
- C++은 시간함수가 없으려나? 파이썬은 있던데,, 부럽다
- 반올림도 기억이 안 나서 구글링을 했다. (반올림, 올림, 버림)은 기억하자!
- map을 쓰는 게 최선이었을까? 근데 바로바로 값에 접근하고, 업데이트해줄 수 있고,
오름차순으로 정렬해줘야 하기에 최선의 방법은 map을 쓰는 것인 거 같다.
물론 2개를 사용하는 것은 살짝 투머치 일수도..?
'CodingTest > Programmers' 카테고리의 다른 글
프로그래머스[Programmers] - 양궁대회(C++)[LV2] (0) | 2023.04.20 |
---|---|
프로그래머스[Programmers] - 광물캐기(C++)[LV2] (0) | 2023.03.30 |
프로그래머스[programmers] - 택배 배달과 수거하기(C++)[LV2] (1) | 2023.03.13 |
프로그래머스[programmers] - 이모티콘 할인 행사(C++)[LV2] (0) | 2023.02.22 |
프로그래머스[programmers] - 쿼드압축 후 개수 세기(C++)[LV2] (0) | 2023.01.04 |