알고리즘/프로그래머스

[C++] 프로그래머스 : 과제 진행하기

금호박 2025. 5. 23. 23:12

문제

https://school.programmers.co.kr/learn/courses/30/lessons/176962?language=cpp

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

풀이

문제에 있는 그대로를 구현해주면 되었다.

 

1. 과목 시작 시간을 기준으로 오름차순 정렬

2. 첫 번째 과목부터 마지막 과목을 제외하고 다음 과목 시작 전까지 완료할 수 있는지를 검사

3-1. 만약 완료할 수 있는 경우, answer 배열에 해당 과목 이름 push. 

     a. 만약 다음 과목 시작 전까지 여유 시간이 있고 중간에 멈춘 과목이 있다면 이어서 진행

3-2. 만약 완료할 수 없는 경우, 다음 과목 시작까지 남은 시간을 playtime에서 빼고 해당 과목을 중지 과목 stack에 넣어줌.

4. 마지막 과목은 무조건 완료할 수 있으므로, answer 배열에 push.

5. 중간에 중지한 과목이 들어있는 stack의 원소를 차례로 pop하여 answer 배열에 push.

 

 나의 경우 처음에 문제를 잘못 봐서 stack이 아닌 deque로 구현되어있지만, push_back()과 push_pop()만을 이용하는 것으로 대신하여 구현했다.

 

코드

#include <string>
#include <deque>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

int timeToMinutes(const string& timeStr) {
    int hour = stoi(timeStr.substr(0, timeStr.find(':')));
    int minute = stoi(timeStr.substr(timeStr.find(':') + 1));
    return hour * 60 + minute;
}

vector<string> solution(vector<vector<string>> plans) {
    vector<string> answer;
    deque<vector<string>> plans_que;
    int finish_num = 0;
    
    // plans[][1]을 기준으로 오름차순 정렬
    sort(plans.begin(), plans.end(), [](const vector<string>& a, const vector<string>& b) {
        return a[1] < b[1];
    });
    
    int i=0;
    while(finish_num !=plans.size()){
        if(i == plans.size()-1){
            answer.push_back(plans[i][0]);
            break;
        } 
        
        // i번재 과목 시작 시간 
        int crr_start_time = timeToMinutes(plans[i][1]);
        
        // 현재 과목 필요 시간 
        int crr_play_time = stoi(plans[i][2]);
        
        // 다음 과목 시작 시간 
        int next_start_time = timeToMinutes(plans[i+1][1]);
   
        // 만약 현재 과목을 종료할 수 있다면 
        if(next_start_time - crr_start_time >= crr_play_time){
            int left_time = next_start_time - crr_start_time - crr_play_time;
            
            // 종료한 과목 수 증가 
            finish_num++;
            answer.push_back(plans[i][0]);
            i++;
                
            // 만약 이미 진행중이던 과목이 있는 경우 
            if(plans_que.size()!=0){
                while(left_time >0){
                    
                    if(plans_que.size()==0) break;
                    
                    // 가장 먼저 큐에 들어온 과목을 이어서 수행
                    vector<string> crr_plan = plans_que.back();
                    plans_que.pop_back();
                    int crr_left_time = stoi(crr_plan[2]);
                    
                    // 이번 과목을 마무리할 수 있는 경우 
                    if(crr_left_time <= left_time){
                        left_time -= crr_left_time;
                        answer.push_back(crr_plan[0]);
                        finish_num++;
                    }
                    
                    // 이번 과목을 마무리할 수 없는 경우 
                    else{
                        crr_left_time -= left_time;
                        crr_plan[2] = to_string(crr_left_time);
                        plans_que.push_back(crr_plan);
                        left_time = 0;
                    }
                } 
            }
        }
        
        // 현재 과목을 종료할 수 없다면 남은 진행 시간 갱신 
        else{
            crr_play_time -= next_start_time - crr_start_time;
            plans[i][2] = to_string(crr_play_time);
            plans_que.push_back(plans[i]);
            i++;
        }
    }
    
    while(plans_que.size()!=0){
        vector<string> crr = plans_que.back();
        plans_que.pop_back();
        string crr_name = crr[0];
        answer.push_back(crr_name);
    }
    return answer;
}

 

 


메모

개인적으로 가장 어려웠던 것은 start 시간을 분 기준으로 변환하여 처리하는 것이었던 것 같다. 구현이 어려운 것은 아니고 해당 함수가 생각이 잘 나지 않아서였는데, 이런 사소한..? 부분을 제외하고는 문제 상황 그대로를 구현하면 되어서 생각보다 어렵지는 않았다. 다른 사람의 풀이를 보면 이 부분을 훨씬 간단하게 풀이한 코드들도 확인할 수 있어서 그런 코드를 참고해보아도 좋을 것 같다.

또 백준과는 다르게 프로그래머스에서는 입력 방식이 고정되어있고 그것을 그대로 이용해야 해서 조금 어렵게 느껴지는 부분도 있는 것 같다. 이건 적응해야 할 것 같다~!!