티스토리 뷰

 

2869번: 달팽이는 올라가고 싶다

첫째 줄에 세 정수 A, B, V가 공백으로 구분되어서 주어진다. (1 ≤ B < A ≤ V ≤ 1,000,000,000)

www.acmicpc.net


1. 문제 내용

 

 

2. 풀이 과정

  • 입력값의 범위에 주의

 최대 입력값이 무려 십 억이다. 따라서 다음과 같이 반복문을 통해 하루하루 이동 값을 체크하는 코드로는 어림도 없다. 즉, 이 문제는 반복문으로 무작정 이동 거리를 구해서 며칠이 걸리는지 구하는 것이 아니라, 며칠이 걸리는지 계산하기 위한 수학 공식을 고민해야 한다.

 공식을 고민해 보자. 하루하루 이동 거리는 a - b이고, 정상에 도착하는 날에는 뒤로 미끄러지지 않는다. 따라서 v / (a - b)가 아니라, (v - a) // (a - b)의 값에 + 1이라는 공식을 세웠다. (+1을 한ㄴ 이유는 v - a에서 이미 하루가 지났다고 간주하기 때문이다)

 

  • 테스트 케이스의 중요성

문제에 제시된 테스트 케이스만으로 코드를 검증하기엔 부족하다. 여러 종류의 테스트 케이스를 고려해 보아야 한다.

  1. 테스트 케이스1: 50 2 50
    • A == V인 경우로, 독특한 상황이기 때문에 if문을 통해 별도로 처리한다.
  2. 테스트 케이스2: 5 1 6
    • (v - a) // (a - b) = (6 - 5) / (5 - 1) = 1 // 4 → 결과: 0
    • 그러나 위 결과는 1이 나와 최종 정답이 1 + 1 = 2가 나와야 한다.
    • 이 공식의 문제는 현재 남아 있는 거리가 하루 동안 이동할 수 있는 거리보다 작으면 아예 이동을 하지 않는다는 것이다. 따라서 (v - a)가 (a - b)보다 클 경우에는 위 공식을 사용하고, (v - a)가 (a - b)보다 작으면 1로 처리한다.
    • 수정된 코드: (v-a) // (a-b) if (v-a) > (a-b) else 1
  3. 테스트 케이스3: 1000000 10 1000000000
    • (v - a) // (a - b) = (1,000,000,000 - 1,000,000) // (1,000,000 - 10) = 999,000,000 // 999,990 → 결과: 999
    • 그러나 위 결과는 1,000이 나와 최종 정답이 1,000 + 1 = 1,001이 나와야 한다.
    • 문제는 바로 나머지를 무시하는 // 때문이다. 실제 999,000,000 / 999,990은 999.009990099901이다. 나머지가 무척 작지만 이를 무시하면 안 된다. 따라서 (v - a) // (a - b)의 값에 나머지가 있다면 무조건 올림하는 ceil() 메서드를 사용한다.

 

 

3. 정답 코드

import math

a, b, v = map(int, input().split())

count = 1
if v == a:
    print(count)
else:
    count += math.ceil((v-a) / (a-b) if (v-a) > (a-b) else 1)
    print(count)

아이디어는 간단하지만, 이러저런 값을 따지는 것이 조금 까다로운 문제였다.

728x90