https://www.acmicpc.net/problem/11399
11399번: ATM
첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)
www.acmicpc.net
오늘은 백준(BOJ)의 11399번: ATM 문제를 풀어보려고 한다.
이 문제는 그리드 문제이며, 비교적 쉽게 풀 수 있는 문제라 워밍업 문제라 생각하면 좋을 것 같다!
그리고 풀면서 든 생각인데, 이 문제는 운영체제도 약간 복습할 수 있는 문제인 것 같다.
문제 조건
인하은행에는 ATM이 1대밖에 없다. 지금 이 ATM앞에 N명의 사람들이 줄을 서있다. 사람은 1번부터 N번까지 번호가 매겨져 있으며, i번 사람이 돈을 인출하는데 걸리는 시간은 Pi분이다.
사람들이 줄을 서는 순서에 따라서, 돈을 인출하는데 필요한 시간의 합이 달라지게 된다. 예를 들어, 총 5명이 있고, P1 = 3, P2 = 1, P3 = 4, P4 = 3, P5 = 2 인 경우를 생각해보자. [1, 2, 3, 4, 5] 순서로 줄을 선다면, 1번 사람은 3분만에 돈을 뽑을 수 있다. 2번 사람은 1번 사람이 돈을 뽑을 때 까지 기다려야 하기 때문에, 3+1 = 4분이 걸리게 된다. 3번 사람은 1번, 2번 사람이 돈을 뽑을 때까지 기다려야 하기 때문에, 총 3+1+4 = 8분이 필요하게 된다. 4번 사람은 3+1+4+3 = 11분, 5번 사람은 3+1+4+3+2 = 13분이 걸리게 된다. 이 경우에 각 사람이 돈을 인출하는데 필요한 시간의 합은 3+4+8+11+13 = 39분이 된다.
줄을 [2, 5, 1, 4, 3] 순서로 줄을 서면, 2번 사람은 1분만에, 5번 사람은 1+2 = 3분, 1번 사람은 1+2+3 = 6분, 4번 사람은 1+2+3+3 = 9분, 3번 사람은 1+2+3+3+4 = 13분이 걸리게 된다. 각 사람이 돈을 인출하는데 필요한 시간의 합은 1+3+6+9+13 = 32분이다. 이 방법보다 더 필요한 시간의 합을 최소로 만들 수는 없다.
줄을 서 있는 사람의 수 N과 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어졌을 때, 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 구하는 프로그램을 작성하시오.
문제 이해하기
P1 = 3, P2 = 1, P3 = 4, P4 = 3, P5 = 2 이라고 할 때,
[1, 2, 3, 4, 5] 순서로 줄을 선다면, 1번 사람은 3분만에 돈을 뽑을 수 있다. 2번 사람은 1번 사람이 돈을 뽑을 때 까지 기다려야 하기 때문에, 3+1 = 4분이 걸리게 된다. 3번 사람은 1번, 2번 사람이 돈을 뽑을 때까지 기다려야 하기 때문에, 총 3+1+4 = 8분이 필요하게 된다. 4번 사람은 3+1+4+3 = 11분, 5번 사람은 3+1+4+3+2 = 13분이 걸리게 된다. 이 경우에 각 사람이 돈을 인출하는데 필요한 시간의 합은 3+4+8+11+13 = 39분이 된다.
줄을 [2, 5, 1, 4, 3] 순서로 줄을 서면, 2번 사람은 1분만에, 5번 사람은 1+2 = 3분, 1번 사람은 1+2+3 = 6분, 4번 사람은 1+2+3+3 = 9분, 3번 사람은 1+2+3+3+4 = 13분이 걸리게 된다고 한다.
그래서, 줄을 서는 방법을 [1, 2, 3, 4, 5], [2, 3, 4, 5, 1], ... ,[2, 5, 1, 4, 3] 등등 여러가지로 해봤을 때, 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값은 1+3+6+9+13 = 32분!
문제에서 이 방법보다 더 필요한 시간의 합을 최소로 만들 수는 없다고 한다.
그렇다면 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 구하는 프로그램은 위의 방법을 사용해야 한다.
아이디어 도출하기
여기서, 문제는 줄을 [1, 2, 3, 4, 5], [3, 4, 2, 1, 5] 등등 어떤 식으로 세워야 최솟값이 될지 파악하는 것이다.
문제를 잘 살펴보면, P1 = 3, P2 = 1, P3 = 4, P4 = 3, P5 = 2일 때, [P2, P5, P1, P4, P3] 순서로 줄을 서야 필요한 시간의 합이 최솟값이 나왔고, 이 순서는 [1분, 2분, 3분, 3분, 4분] 이런 식으로 시간이 적게 걸리는 사람순으로 서야 하는 것을 알 수 있다.
그렇다면, 코드를 짤 때 시간이 적게 걸리는 순으로 줄을 세워 필요한 시간의 합을 계산하는 식으로 하면 되지 않을까?
문제 풀이 (코드)
위의 아이디어를 바탕으로 코드를 짜보도록 하자!
1.
첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다.
둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)
-> 사람의 수 입력으로 받자
-> 각 사람이 돈을 인출하는데 걸리는 시간 Pi를 입력받자 (java의 ArrayList 이용)
2.
입력받은 Pi들을 시간이 적게 걸리는 순으로 줄을 세우자
-> 오름차순으로 정렬 (.sort() 메소드 이용)
3.
필요한 시간의 합을 계산하자
-> withdrawTime = 각 사람이 돈을 인출하는데 걸리는 시간
-> rslt = 필요한 시간의 합의 최솟값
-> withdrawTime을 rslt에 더함!
4.
rslt(필요한 시간의 합의 최솟값=최종결과값)를 출력!
최종 코드
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 사람의 수와 각 사람이 돈을 인출하는데 걸리는 시간 Pi 입력
int n = scan.nextInt();
ArrayList<Integer> times = new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
times.add(scan.nextInt());
}
// 입력받은 Pi(times)를 오름차순 정렬
Collections.sort(times);
// 필요한 시간의 합 계산
int rslt = 0;
int withdrawTime = 0;
for (int i = 0; i < n; i++) {
withdrawTime += times.get(i);
rslt += withdrawTime;
}
// 필요한 시간의 합의 최솟값 출력
System.out.print(rslt);
scan.close();
}
}
여기서 주의할 점은 백준(BOJ)에서 자바 코드를 제출할 때,
Class명은 무조건 Main으로 해야 한다!
(이거 안 하면 컴파일 오류나서 눈물 남..)
'알고리즘' 카테고리의 다른 글
[백준 BOJ][JAVA] 2606번: 바이러스 (0) | 2022.01.30 |
---|---|
[백준 BOJ][JAVA] 10886번: 덱 (0) | 2022.01.29 |
[백준 BOJ][JAVA] 2164번: 카드2 (0) | 2022.01.28 |
[백준 BOJ][JAVA] 9012번: 괄호 (0) | 2022.01.22 |
[백준 BOJ][C언어] 10773번: 제로 (0) | 2022.01.22 |