본문 바로가기

별걸다하는 IT/알고리즘 문제풀이

[COCI 2009/2010기출, 백준 2884번] 알람 시계 문제 풀이 및 해설 (C/C++/Java) 문제 해설

안녕하세요 정말 오랜만에 찾아뵙는 알고리즘 풀이입니다!

오늘은 if문 분류로 되어있는 문제로 가져왔어요.


출처: COCI 2009/2010년도 7th round 1번 문항

출처: 백준 2884번

정답률: 40.588% 

[2884번] 알람 시계 (SPAVANAC)

문제

기출문제 사진

상근이는 매일 아침 알람을 듣고 일어난다. 알람을 듣고 일어나면 다행이겠지만, 항상 조금만 더 자려는 마음 때문에 매일 학교를 지각하고 있다. 상근이는 모든 방법을 동원해보았지만, 조금 더 자려는 마음은 그 어떤 것도 없앨 수 없었다. 이런 상근이를 불쌍하게 보던, 창영이는 자신이 사용하는 방법을 추천해주었다. 바로 "45분 일찍 알람 설정하기"이다. 이 방법은 단순하다. 원래 설정되어 있는 알람을 45분 앞서는 시간으로 바꾸는 것이다. 어차피 알람 소리를 들으면, 알람을 끄고 조금 더 잘 것이기 때문이다. 이 방법을 사용하면 매일 아침 더 잤다는 기분을 느낄 수 있고, 학교도 지각하지 않게 된다. 현재 상근이가 설정한 알람 시각이 주어졌을 때, 창명이의 방법을 사용한다면, 이를 언제로 고쳐야 하는지 구하는 프로그램을 작성하시오. 

 

입출력

입력: 

첫째 줄에 두 정수 H와 M이 주어진다. (0 <= H <= 23, 0<=M<=59) 그리고 이것은 현재 상근이가 설정해 놓은 알람 시간 H시 M분을 의미한다. 입력 시간은 24시간 표현을 사용한다. 24시간 표현에서 하루의 시작은 0:0(자정)이고 끝은 23:59(다음날 자정 1분 전)이다. 시간을 나타낼 때, 불필요한 0은 사용하지 않는다.

 

출력:

첫째 줄에 상근이가 창영이의 방법을 사용할 때, 설정해야 하는 알람 시간을 출력한다. (입력과 같은 형태로 출력하면 된다.)

 

같이 풀어봅시다~~!

 

ANSWER 해설

해당 문제는 규칙만 알면 너무 쉬워요. 정말 너무 쉬운....

가장 먼저, 만약 현재 시간이 45분보다 크면 그냥 현재 분에서 45분을 빼주면 되겠죠? 시간은 그대로일거고...

[C++]

#include <iostream>
using namespace std;
int main()
{
	const int setting = 45; //문제에서 주어진 값
    int hour, min; //입력받을 값 선언
    cin >> hour >> min; //시간과 분을 입력받음
    
    if(min >= setting) min -= 45;
	return 0;
}

그럼 만약 현재 시간이 45분보다 작다면 어떻게 계산할 수 있을까요?

우리 빼기 할 때, 빼기 모자르면 앞에서 10 빌려와서 빼죠? 14 - 7 하면, 일의자리에서 계산한다고 할 때 4에서 7을 못빼니까 앞에 1을 빌려와서 10에서 7을 뺀 뒤 계산한 값의 3과 남은 4를 더해서 7! 이렇게 하잖아요. 

 

뭐 시간도 마찬가지겠죠. 첫 번째 예제의 경우 10분에서 45분을 뺄 수 없어요. 그니까 60분을 빌려와서 (60-45)+10 = 25 ! 이렇게하면 제대로된 계산을 할 수 있습니다. 물론 빌려왔으니까 시간은 -1 해줘야겠죠.

근데 주의할 점이 있어요. 2번째 예제처럼 0시일 경우 거꾸로 가서 23시가 되어야해요. 시계는 순환하기 때문이죠. 그러므로 아래처럼 작성해줄 수 있습니다.

[C++ 전체 소스코드]

#include <iostream>
using namespace std;
int main()
{
	const int setting = 45;
	int hour, min = 0;
	cin >> hour >> min;
	if (min < setting)
	{
		min = (min + 60 - setting); 
		hour = (hour + 24 - 1) % 24;
	}
	else
	{
		min -= setting;
	}
	cout<<hour<<" "<<min;
	return 0;
}

 이게 별거 아닌데 좀 길어보인다, 그럼 아래처럼 작성줄 수 있어요.

[C++ 전체 소스코드]

#include <iostream>
using namespace std;
int main()
{
	const int setting = 45;
	int hour, min = 0;
	cin >> hour >> min;
	min -= setting;
	if (min < 0)
	{
		min += 60;  
		hour = (hour + 24 - 1) % 24;
	}
	printf("%d %d", hour, min);
	return 0;
}

일단, 45분을 빼준다음에 마이너스이면, 시간을 내려야하는거니까~!

계산 순서 차이일뿐 똑같은 로직입니다. 

 

[C언어]

C언어라면 단순히 cin이나 cout대신 scanf, printf 만 써주면 돼요 ㅎㅎ 딱히 언어를 구별지을만한 코드가 들어가진 않았으므로..?

그렇다면 다른 방법으로 풀어봅시다. 이번에는 비율적인 관점으로 가볼게요. 시계는 빙글 빙글 돌아요.

여기서 45분이 앞섰다는건, 4분의 3이 앞섰다는거고, 그건 4분의 1, 즉 15분만큼 앞으로 갔다는거랑 같은 말이죠 (분만 따졌을 때) 

-45분이나 +15분이나 분 관점에선 같다.

사실 앞에 코드랑도 결국 같은 말이예요 (60-45)+10 은 결국 15 + 10 이니까 10분에 15를 더한거랑 똑같잖아요?!

[C언어 전체코드]

#include <stdio.h>
int main(){
    int h, m;
    scanf("%d %d", &h, &m);
    printf("%d %d", (h+23+(m+15)/60)%24, (m+15)%60);
}

 따라서 분은 (m+15)%60으로 구해도 같은말~~~

시간도 24시 기준이니까 24시 이상 나왔을 경우 변경을 위해 모듈로 나눠줍시다. 

 

[JAVA 자바]

남은 것은 자바인가..! 원리는 똑같, 언어만 다를 뿐 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
	public static void main(String[] args) throws IOException{
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int hour = Integer.parseInt(st.nextToken());
        int min = Integer.parseInt(st.nextToken());
        
        min -= 45;
        if (min <0) 
        {
            min +=60; hour -= 1;
            if(hour<0) hour = 23; //위에처럼 모듈 안쓰고 이렇게 단순하게 해줘도 됨
        }
        System.out.println(hour+" "+min);
    }
}

[시간 76ms, 코드길이 698B]

사실 속도때문에 저 버퍼드리더를 쓴거지, 아래처럼 그냥 스캐너로 입력받아도 됩니다.

import java.io.IOException;
import java.util.Scanner;

public class Main{
	public static void main(String[] args) throws IOException{
    	Scanner sc = new Scanner(System.in);
        int hour = sc.nextInt(); 
        int min = sc.nextInt();
        min -= 45;
        if (min <0) 
        {
        	min +=60; hour -= 1;
		if(hour<0) hour = 23; //위에처럼 모듈 안쓰고 이렇게 단순하게 해줘도 됨
        }
        System.out.println(hour+" "+min);
    }
}

[시간 104ms, 코드길이 475B]

다른 사람 풀이 참조하기

C언어
JAVA 언어

오늘은 여기까지입니다. 도움이 되셨다면 좋아요, 덧글 또는 광고보답은 어떤가요?