본문 바로가기
알고리즘

[백준] 알람 시계 [C++, 시간 계산을 어떻게 생각 했을까?]

by itstime0809 2023. 8. 28.
728x90

구현

https://www.acmicpc.net/problem/2884

 

2884번: 알람 시계

상근이는 매일 아침 알람을 듣고 일어난다. 알람을 듣고 바로 일어나면 다행이겠지만, 항상 조금만 더 자려는 마음 때문에 매일 학교를 지각하고 있다. 상근이는 모든 방법을 동원해보았지만,

www.acmicpc.net

 

코드

#include <iostream>
using namespace std;

int time (int h, int m) {
	if (m - 45 < 0) {
		if (h == 0 ) {
			h = 24;
		}
	} 
	int result = ((h*60)+m)-45;
	return result;
}

int main(void) {
	ios_base::sync_with_stdio(false); cin.tie(NULL);

	int h, m;
	cin >> h >> m;

	int result = time(h, m);
	cout << result / 60 << " " << result % 60 << "\n";
	
	return 0;
}

 

설명

 해당 문제는 알림 시계라는 문제인데 처음에 가볍게 생각하다가 반례에서 심하게(?) 데인 문제라고 생각이 들어서 흥미로워 작성하려고 합니다. 우선 해당 문제의 가장 중요한 건 "45분 일찍 알림을 맞춘다"는 설정이다. 시간 계산을 잘하는 것과 시간 계산을 코드로 적는 건 너무나 다른 영역이기 때문에 머릿속으로는 당연히 이런 답이 나와야 하겠지만 코드 상으로는 알려주지 않으면 나오지 않으니 하나씩 살펴보자. 가장 먼저 면밀히 살펴보아야 할 것은 h, m의 조건이다. 대부분 시간문제일 경우 0시부터 시작하고 23시까지로 정의해 두고 분 같은 경우에도 0부터 59분까지를 정의한다. 그때 0시는 자정을 의미하고 12시는 정오를 의미한다. 따라서 하루라는 개념은 23:59분까지가 하루의 개념으로 작용된다. 이는 일상생활에서도 당연하게 적용되는 시간 법칙이다. 그럼 이제 생각해 보기 힘든 부분(?)을 생각해 본다면 총 3가지로 나눠볼 수 있을 것 같다.

 

 

분 - 45 했을때 그 결과가 0보다 크다면?

분 - 45 했을때 그 결과가 0보다 작다면?

분 - 45 했을때 그 결과가 0과 같다면?

 

 

 위 세가지 질문에 하나씩 차근차근 대답해 나가다 보면 공통적인 풀이를 찾을 수 있었다. 첫 번째부터 보면 주어진 분에서 45분을 뺐을때 즉 45분 전이라고 했을 때 시간이 만약에 0이라고 어떻게 해야 될까? 위에서 0시는 자정을 의미한다. 따라서 저녁 12시가 아니라 24시간으로 계산해야 된다는 것이다. 그럼 다시 돌아와서 시간이 0시라고 했을 때 45분을 빼서 0보다 크다면? 대략 분을 46분 정도로 생각해 본다면 24시 1분이 될 것이다. 왜냐하면 46-46를 빼기 때문이다. 그럼 1분이 나오게 되지만 0시는? 이 문제에서 0시는 당연히 0시로 나와야 한다. 왜냐하면 0시를 자정으로 정의해 놓았기 때문이다. 따라서 시간은 0시 1분이 되어야 정답인 것이다. 만약 0시를 24시로 정의하라고 했다면 24시 1분이 정답이겠지만 자정을 0시로 정의했기 때문에 출력 또한 자정이라면 0시로 출력이 되어야 정답인 것이다. 그럼 두 번째 질문에 대답해 보면 0보다 작은 경우는 어떤 경우가 있을까? 45보다 작은 분을 뺀다고 한다면 44-45 = -1이 나온다. -1분이라는 게 존재하지 않기 때문에 시간에서 빌려온다는 개념을 이용할 수 있다. 따라서 60분을 빌려와 빼야 될 분에서 산술연산을 진행한 후 원래 분에 더해서 분을 구해준다. 하지만 여기서 또 하나 시간이 0이라면 어떻게 될까? 0시에서 빌려올 수 있는가? 없다. 따라서 분에서 뺐을때 0보다 작은 수라면 24시에서 빌려와야 한다. 따라서 0시 44분이라면 23시 59분이 나와야 한다. 그다음 0이랑 같다면 어떻게 될까? 해당 시간 그대로 출력이 될 것이다. 만약 0시 45분이라면 0시 0분이 될 것이고, 1시 45분이라면 1시 0분이 될 것이다. 불필요한 0은 제거하라고 했기 때문에 01시 같은 형태로 출력이 되지 않는다. 그럼 이제 공통점을 좀 찾아보자.

 

 0보다 작은 경우에는 24시에서 빌려와야 한다. 따라서 h = 24로 변경해 빌려주는 수로 작용 되어야 한다. 그래야 0 44분은 23시 59분이 될 수 있기 때문에 0보다 큰 경우에는 어떤 경우에도 즉 0시46분에도 0시 1분으로 출력이 되며, 1시 46분인 경우에도 1시 1분이 된다. 0인 경우에도 0시 45분은 0시 0분, 1시 45분은 1시 0분이다. 그럼 위에서 찾아낼 수 있는 건 빌려주는 수로 작용 되어야 하는 건 분에서 - 45분을 뺐을때 0보다 작아지는 순간이다. 이 순간에는 -1이라는 분은 없기 때문에 0분은 있어도 -1이라는 분은 없다. 그전 시간대기 때문이니까 그렇기 때문에 0시일 때는 빌려주는 수를 24시로 고쳐서 생각해야 된다는 것이다. 그 외에는 1시 44분이라고 하여도 분으로 전부 고쳐서 생각해 보면 전부 잘 나오는 걸 확인할 수 있다. 그래서 이번 문제는 0시를 어떻게 다룰지를 고민해야 되는 문제라고 생각한다.