문제 링크 : https://www.acmicpc.net/problem/19583

 

19583번: 싸이버개강총회

첫번째 줄에는 개강총회를 시작한 시간 S, 개강총회를 끝낸 시간 E, 개강총회 스트리밍을 끝낸 시간 Q가 주어진다. (00:00 ≤ S < E < Q ≤ 23:59) 각 시간은 HH:MM의 형식으로 주어진다. 두번째 줄부터는

www.acmicpc.net

문제 요약

 

1. 개강총회 시작시간(s), 개강총회 종료시간(e), 스트리밍 종료시간(q)가 주어집니다.

2. 아래 두 조건을 모두 맞추어 로그를 남겼을 경우 해당 학회원은 출석이 인정됩니다.

(1) 개강총회 시작시간 이하에 로그를 남김

(2) 개강총회 종료시간 이상, 스트리밍 종료시간 이하에 로그를 남김
3. 출석이 인정된 학회원이 모두 몇명인지 숫자를 출력하세요. 

 

핵심 포인트

 

문자열 관련 메소드를 잘 알고있으면 쉽게 풀 수 있습니다.

단, 사용자가 특정 시간대에 존재했는가 아닌가는 int형으로 형변환을 하여 접근할 경우 수월하게 풀 수 있습니다.

 

문제 풀이

 

1. 전역함수와 input함수 입니다. input함수를 아래와 같이 별도로 구현하여 개강총회 시작시간, 종료시간, 스트리밍 종료시간의 시간과 분다위를 별도의 int변수로 저장합니다.

string s,e,q,temp; // 개총시작, 개총종료, 스트리밍 종료
int s1,s2,e1,e2,q1,q2;
unordered_set<string> entry;
unordered_set<string> ans;

void input(){
    cin >> s >> e >> q;
    temp = s.substr(0,2);
    s1 = stoi(temp);
    temp = s.substr(3,5);
    s2 = stoi(temp);
    temp = e.substr(0,2);
    e1 = stoi(temp);
    temp = e.substr(3,5);
    e2 = stoi(temp);
    temp = q.substr(0,2);
    q1 = stoi(temp);
    temp = q.substr(3,5);
    q2 = stoi(temp);
}

참고로 input()함수에 쓰인 메소드들의 설명은 다음과 같습니다.

stoi(문자열) : 문자열을 int형으로 변환합니다. 
문자열변수.substr(자르기시작 위치, 자르기 시작 종료 미만) : 해당 문자열 변수에서 자르기 시작위치 이상, 자르기 시작 종료 미만에 위치한 문자열을 저장합니다.

둘다 별도의 헤더가 필요하지 않습니다.

 

2. 학회원의 입장시간을 변수 t, 이름을 변수 n에 저장합니다.

t와 n이 입력될때까지는 while문을 지속합니다.

    string t,n; // 시간, 이름
    while(cin >> t >> n){
        int h=0,m=0; // 1
        temp = t.substr(0,2);
        h = stoi(temp);
        temp = t.substr(3,5);
        m = stoi(temp);
        int entry1 = (s1*100+s2), user1 = (h*100+m); // 2
        // 입장시간 이하일 경우
        if(user1<=entry1){ // 3
            if(entry.find(n)==entry.end()) entry.insert(n);
        }
        // 종료시간 ~ 스트리망 종료시간일 경우
        int exit1 = (e1*100+e2), exit2 = (q1*100+q2), user2 = (h*100+m); // 4
        if(user2>=exit1&&user2<=exit2){ // 5
            auto it = entry.find(n);
            auto it2 = ans.find(n);
            if(it!=entry.end()&&it2==ans.end()){ // 6
                ans.insert(n);
            }
        }
    }

(1) 학회원의 입장 시간과 분을 h,m에 각각 저장합니다. 이때 substr 메소드를 활용합니다.

(2) 개강총회 시작시간을 int로 변환하여 저장하고 학회원의 입장시간을 int로 변환하여 저장합니다.

예를들어 개강총회 시작시간이 18:52이었을 경우, 1852로 저장합니다.

(3) 학회원의 입장시간이 개강총회 시간시간 이하이며, entry에 학회원의 이름이 없을 경우 추가해줍니다.

참고로 entry는 unordered_set으로 전역변수에 선언되었습니다.

(4) 2번과 같은 논리로 개강총회 종료시간, 스트리밍 종료시간, 학회원의 퇴장시간을 int로 변환해 저장합니다.

(5) 학회원의 퇴장시간이 개강총회 종료시간 이상, 스트리밍 종료시간 이하일 경우

(6) 동시에 학회원의 이름이 entry(입장이 인증됨)에 있으며, ans(종료가 인증됨)에 없을 경우, ans에 추가해줍니다.

 

3. while문을 빠져나오면 ans의 사이즈를 출력합니다.

cout << ans.size() << "\n";

 

#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_set>
using namespace std;

string s,e,q,temp; // 개총시작, 개총종료, 스트리밍 종료
int s1,s2,e1,e2,q1,q2;
unordered_set<string> entry;
unordered_set<string> ans;

void input(){
    cin >> s >> e >> q;
    temp = s.substr(0,2);
    s1 = stoi(temp);
    temp = s.substr(3,5);
    s2 = stoi(temp);
    temp = e.substr(0,2);
    e1 = stoi(temp);
    temp = e.substr(3,5);
    e2 = stoi(temp);
    temp = q.substr(0,2);
    q1 = stoi(temp);
    temp = q.substr(3,5);
    q2 = stoi(temp);
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    input();
    string t,n; // 시간, 이름
    while(cin >> t >> n){
        int h=0,m=0;
        temp = t.substr(0,2);
        h = stoi(temp);
        temp = t.substr(3,5);
        m = stoi(temp);
        int entry1 = (s1*100+s2), user1 = (h*100+m);
        // 입장시간 이하일 경우
        if(user1<=entry1){
            if(entry.find(n)==entry.end()) entry.insert(n);
        }
        // 종료시간 ~ 스트리망 종료시간일 경우
        int exit1 = (e1*100+e2), exit2 = (q1*100+q2), user2 = (h*100+m);
        if(user2>=exit1&&user2<=exit2){
            auto it = entry.find(n);
            auto it2 = ans.find(n);
            if(it!=entry.end()&&it2==ans.end()){
                ans.insert(n);
            }
        }
    }
    cout << ans.size() << "\n";
    return 0;
}

 

위의 풀이법 말고도 모든 시간에 있는 ':'를 제거하여 한번에 숫자로 변환하면 보다 코드가 깔끔해지는 방법도 있습니다.