문제
땅 위에 달팽이가 있다. 이 달팽이는 높이가 V미터인 나무 막대를 올라갈 것이다.
달팽이는 낮에 A미터 올라갈 수 있다. 하지만, 밤에 잠을 자는 동안 B미터 미끄러진다. 또, 정상에 올라간 후에는 미끄러지지 않는다.
달팽이가 나무 막대를 모두 올라가려면, 며칠이 걸리는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 세 정수 A, B, V가 공백으로 구분되어서 주어진다. (1 ≤ B < A ≤ V ≤ 1,000,000,000)
2 1 5
출력
첫째 줄에 달팽이가 나무 막대를 모두 올라가는데 며칠이 걸리는지 출력한다.
4
내 코드
이게 까다로운 점은 마음같아선 그냥 하루에 올라가는 길이 즉, up - down으로 목표 거리를 나눠주고 싶지만, 대부분의 경우, 마지막 날에는 낮에 올라가는 도중에 목표지점에 도달하는 것이 현실이라 생각과는 거리가 멀다는 점이다.
예를 들어 낮에 9 미터 올라가고 밤에 8미터 미끄러지는 데, 목표지점이 5미터라면 이미 첫날 낮에 도달했을 것이다.
따라서 이러한 과정을 그대로 코드로 옮긴 것이 첫 제출이었다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int up = sc.nextInt();
int down = sc.nextInt();
int goal = sc.nextInt();
int count = 1;
while (goal - up > 0) {
goal -= (up - down);
count++;
}
System.out.println(count);
}
}
하루가 지나가는 것을 count로하고 첫째날 낮에 올라간 만큼 목표 거리에서 up을 빼줬을 때 0보다 크다면, 도달하지 못했으니 하루 동안 간 거리 up - down을 빼주고 count를 올려 둘쨋날로 만들어준다. 둘쨋날 낮에 up만큼 빼고 남은 거리가 아직도 0보다 크다면 다시 하루를 보내준다. 이런 방식으로 코드를 짜면 답은 잘 나오지만 시간 제한은 0.15초라서 시간초과가 떠버린다.
그렇다면 이렇게 하루하루를 재현하는 코드는 시간 안에 불가능하다. 완전히 다른 접근 방식이 필요한데, 나는 목표 지점에 도달하는 데 걸리는 날짜를 n으로 해줬을 때 goal이 n번째 날 낮에 도착하려면 (n - 1)번째 날에 도달하는 최고 지점보다는 goal이 높아야 하고 n번째 날에 도달하는 최고 지점(goal에서 멈추지 않는다고 가정)보다는 같거나 낮아야 한다고 조건을 걸었다. 이 조건을 수식으로 쓰면
(n - 2)(up - down) + up < goal <= (n - 1)(up - down) + up 이렇게 되고
우리가 알고 싶은 것은 n이므로 n 중심으로 조건문을 바꿔주면
(goal - up) / (up - down) + 1 <= n < (goal - up) / (up - down) + 2
이렇게 된다.
우리는 이 범위 안에 있는 n만 구하면 되므로 반복문을 돌리던 아까의 방식보다 훨씬 실행이 짧아진다.
그런데 n은 정수기 때문에 (goal - up) / (up - down) 의 결과가 정수냐 소수냐에 따라 n의 값이 달라지므로 조건에 따라 결과를 나눠 출력했다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int up = sc.nextInt();
int down = sc.nextInt();
int goal = sc.nextInt();
// (n - 2)(up - down) + up < goal <= (n - 1)(up - down) + up
// (n - 2)(up - down) < goal - up <= (n - 1)(up - down)
// n - 2 < (goal - up) / (up - down) <= n - 1
// n < (goal - up) / (up - down) + 2 && n >= (goal - up) / (up - down) + 1
if ((goal - up) % (up - down) == 0) {
System.out.println((goal - up) / (up - down) + 1);
} else {
System.out.println((goal - up) / (up - down) + 2);
}
}
}
'자바 자료구조 & 알고리즘 > 알고리즘 문제 풀이' 카테고리의 다른 글
백준 1011번 - Fly me to the Alpha Centauri (0) | 2020.08.26 |
---|---|
백준 2775번 - 부녀회장이 될테야 (0) | 2020.08.26 |
백준 2839번 - 설탕 배달 (0) | 2020.08.26 |