백준 알고리즘 | 1712번 문제: 손익분기점


출처

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

문제

월드전자는 노트북을 제조하고 판매하는 회사이다. 노트북 판매 대수에 상관없이 매년 임대료, 재산세, 보험료, 급여 등 A만원의 고정 비용이 들며, 한 대의 노트북을 생산하는 데에는 재료비와 인건비 등 총 B만원의 가변 비용이 든다고 한다.

예를 들어 A=1,000, B=70이라고 하자. 이 경우 노트북을 한 대 생산하는 데는 총 1,070만원이 들며, 열 대 생산하는 데는 총 1,700만원이 든다.

노트북 가격이 C만원으로 책정되었다고 한다. 일반적으로 생산 대수를 늘려 가다 보면 어느 순간 총 수입(판매비용)이 총 비용(=고정비용+가변비용)보다 많아지게 된다. 최초로 총 수입이 총 비용보다 많아져 이익이 발생하는 지점을 손익분기점(BREAK-EVEN POINT)이라고 한다.

A, B, C가 주어졌을 때, 손익분기점을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 21억 이하의 자연수이다.

출력

첫 번째 줄에 손익분기점 즉 최초로 이익이 발생하는 판매량을 출력한다. 손익분기점이 존재하지 않으면 -1을 출력한다.

예제 입력 1

1000 70 170

예제 출력 1

11

예제 입력 2

3 2 1

예제 출력 2

-1

예제 입력 3

2100000000 9 10

예제 출력 3

2100000001

노트

이 문제에서 설명하는 손익분기점은 회계학에서 정의하는 손익분기점과 다를 수 있다.

알고리즘 분류

  • 수학
  • 사칙연산

문제 풀이

손익분기점이 존재하는 경우
A(고정 비용)=1000, B(가변 비용)=70, C(1대 가격)=170, n(판매 대수)=?

판대 대수 총 비용 총 수입 비교
수식 A + (B * n) = 총 비용 C * n = 총 수입
1 1000 + 70 * 1 = 1070 170 * 1 = 170
2 1000 + 70 * 2 = 1140 170 * 2 = 340
3 1000 + 70 * 3 = 1210 170 * 3 = 510
4 1000 + 70 * 4 = 1280 170 * 4 = 680
5 1000 + 70 * 5 = 1350 170 * 5 = 850
6 1000 + 70 * 6 = 1420 170 * 6 = 1020
7 1000 + 70 * 7 = 1490 170 * 7 = 1190
8 1000 + 70 * 8 = 1560 170 * 8 = 1360
9 1000 + 70 * 9 = 1630 170 * 9 = 1530
10 1000 + 70 * 10 = 1700 170 * 10 = 1700 비용 = 수입
11 1000 + 70 * 11 = 1770 170 * 11 = 1870

손익분기점이 존재하지 않는 경우
A(고정 비용)=3, B(가변 비용)=2, C(1대 가격)=1

판대 대수 총 비용 총 수입
1 3 + 2 * 1 = 5 1 * 1 = 1
1 3 + 2 * 2 = 7 1 * 2 = 2

가변 비용(B)가 1대 가격(C)보다 작게 되면, 손기분기점이 존재하지 않는다.

B >= C | 2 >= 1

통과 하지 못한 코드

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 {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {

            // 입력
            StringTokenizer input = new StringTokenizer(br.readLine(), " ");
            final long a = Long.parseLong(input.nextToken()); // 고정 비용
            final long b = Long.parseLong(input.nextToken()); // 가변 비용
            final long c = Long.parseLong(input.nextToken()); // 1대 가격

            // 계산
            if (b >= c) { // 가변 비용이 1대 가격보다 같거나 크면, 손기분기점이 없다. 3 2 1 인 경우, 2 >= 1
                System.out.println(-1);
                return;
            }

            int n = 0; // 판매 대수
            long cost = 0; // 총 비용(=고정 비용+가변 비용)
            long income = 0; // 총 수입(판매 비용)

            do {
                n++;

                cost = a + (b * n);
                income = c * n;

                // 디버그용
                //System.out.println("n=" + n + ", cost=" + cost + ", income=" + income);
            } while (cost >= income);

            // 출력
            System.out.println(n);
        }
    }
}

수식대로 차례대로 계산하니 결과를 맞는데, 오래걸려서 “시간 초과"로 실패하였다.

그렇다면, 수식대로 계산을 계속 할게 아니라, 계산 공식을 만들어야 할 거 같다. 위에 테이블을 자세히 보면, 총 비용과 총 수입이 같아지는 순간 이후에 손익분기점이 된다는 것을 알 수 있다.

이를 수식으로 표현하여 공식을 구하면 아래와 같다.

고정 비용 + (가변 비용 * 판매 대수) = 1대 가격 * 판매 대수 = 손익분기점 직전
A + (B * n) = C * n
A = C * n - B * n
A = (C - B) * n

A / (C - B) = n -> 계산 공식!!

계산 공식에 예제 수를 대입 시켜 보면 아래와 같다.

A(고정 비용)=1000, B(가변 비용)=70, C(1대 가격)=170  
A / (C - B) = n
1000 / (170 - 70) = 10

총 비용과 총 수입이 같아지는 순간. 즉, 손익분기점 직전은 10대를 팔았을 경우이다. 여기에 1을 더하면 11대를 팔았을 손익분기점을 넘기게 된다.

A / (C - B) + 1 = n -> 최종 계산 공식!!

이를 바탕으로 프로그램을 만들어 보자.

통과한 코드

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 {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {

            // 입력
            StringTokenizer input = new StringTokenizer(br.readLine(), " ");
            final long a = Long.parseLong(input.nextToken()); // 고정 비용
            final long b = Long.parseLong(input.nextToken()); // 가변 비용
            final long c = Long.parseLong(input.nextToken()); // 1대 가격

            // 계산
            int count = -1; // 판매 대수
            if (b < c) {
                // 판매 대수 = 고정 비용 / (1대 가격 - 가변 비용) + 1
                count = (int) ((a / (c - b)) + 1);
            }

            // 출력
            System.out.println(count);
        }
    }
}