SOJ ONLINE JUDGE

문제 79

종이의 집

내 상태
미제출
난이도
79번 문제 난이도 보기
Bronze IV
출제자
pizzaroot
시간 제한
1000 ms
메모리 제한
512 MB
79번 문제 태그 보기
구현정렬

세종대학교에는 금고가 $N$개 존재한다. 종이는 금고를 털려고 한다!

금고를 너무 많이 털면 들킬 수 있기 때문에 최대 $2$개의 금고만 털려고 한다!

각 금고에 들어있는 금액이 주어지면 털 수 있는 금액의 최댓값을 출력하라.

입력

첫 번째 줄에 정수 $N$이 주어진다. $(2 \le N \le 100)$

두 번째 줄에 각 금고에 들어 있는 금액을 의미하는 $N$개의 정수 $x_1, x_2, \cdots, x_N$이 공백으로 구분되어 주어진다. $(0 \le x_i \le 500)$

출력

첫 번째 줄에 털 수 있는 금액의 최댓값을 출력한다.

예제 입력 1

3
9 2 3

예제 출력 1

12

예제 입력 2

4
5 2 4 5

예제 출력 2

10

공식 해설 풀이 스포일러 보기 접기

금액이 모두 음수가 아니고 금고가 적어도 두 개 있으므로, 금고를 두 개 선택해도 하나만 선택할 때보다 나빠지지 않는다. 선택한 금고보다 돈이 많은 다른 금고가 있다면 바꾸는 것이 유리하므로 가장 큰 두 금액의 합이 답이다.

전체를 정렬할 필요 없이 지금까지의 가장 큰 값과 두 번째로 큰 값만 유지한다. 새 금액이 최댓값보다 크면 기존 최댓값을 두 번째로 옮기고 최댓값을 바꾼다. 그렇지 않으면 두 번째 값과 비교하여 갱신한다.

두 값을 $0$으로 시작하면 금액이 모두 $0$이어도 처리된다. 같은 금액의 금고도 서로 다른 금고이므로 최댓값과 같은 금액이 다시 나오면 두 번째 값에 들어갈 수 있어야 한다.

시간복잡도는 $O(N)$, 추가 공간복잡도는 $O(1)$이다.

구현 · 언어별 풀이

C++ 구현

가장 큰 두 값을 담는 int 변수 두 개를 $0$으로 초기화한다. 새 값이 첫 번째 값보다 크면 기존 첫 번째를 두 번째로 옮기고, 그렇지 않으면 두 번째와 비교한다. 같은 최댓값이 두 번 들어올 때도 두 금고를 모두 셀 수 있어야 한다.

C 구현

최댓값 두 개를 int 변수로 유지한다. 같은 값도 서로 다른 금고라면 두 번 선택할 수 있으므로 중복을 제외하지 않는다. 합의 최댓값은 1000이라 int로 충분하다.

Python 구현

최댓값과 두 번째 값을 변수로 갱신하거나 정렬 뒤 마지막 두 값을 더한다. set으로 만들면 값이 같은 두 금고를 잃는다. 금고 번호의 서로 다름과 금액의 서로 다름을 혼동하지 않는다.

Java 구현

두 최댓값은 int로 유지한다. 입력 금액이 0 이상이라 초기값 0을 사용할 수 있고 동일한 최대 금액도 둘 다 반영한다. 별도 heap이나 금고 객체는 필요 없다.

Rust 구현

두 최대 금액을 i32 변수로 갱신한다. 같은 금액도 두 위치면 모두 사용할 수 있다. 답이 1000 이하이므로 i64나 u128을 사용할 이유는 없다.

JavaScript 구현

가장 큰 금액 두 개를 Number 변수에 유지한다. 모든 금액이 $0$ 이상이므로 초기값을 둘 다 $0$으로 둘 수 있다. 새 값이 최댓값 이상이면 기존 최댓값을 두 번째로 넘긴다.

let first = 0, second = 0;
for (const x of amounts) {
    if (x >= first) {
        second = first;
        first = x;
    } else if (x > second) {
        second = x;
    }
}
console.log(first + second);

같은 금액의 서로 다른 금고도 두 개 고를 수 있으므로 Set으로 중복을 제거하지 않는다. 합은 $1\,000$ 이하이며 BigInt나 우선순위 큐는 필요 없다.

제출

편집기에서 나가려면 Esc를 누른 뒤 Tab 또는 Shift와 Tab을 누르세요.