티어: 골드 3
알고리즘: 그리디
총 N개의 역을 지나가는 기차가 있다. (첫 역과 마지막 역도 포함한다)
기차가 첫 역을 출발할 때와 마지막 역에 도착할 때, 탑승하고 있는 승객은 아무도 없다. 각 역에서 기차를 타는 승객의 수와 기차에서 내리는 승객의 수는 입력으로 주어진다.
각 승객은 기차를 타고 역 몇 개를 지난 뒤에 지하철에서 내리고, 같은 열차를 두 번 이상 타지 않는다.
이 기차에는 기차표를 검사하는 직원이 타고 있다. 이 직원은 기차가 첫 번째 역에서 두 번째 역으로 가는 동안 기차를 타고 있는 모든 승객의 기차표를 검사한다. 그 다음에는 기차가 역 K개를 지날 때마다 표를 검사한다. (일반화 하면 aK+1 번째 역에서 aK+2 번째 역으로 가는 동안 검사한다) 따라서, 기차를 타고 있는 동안 기차표를 한 번도 검사받지 않는 승객이 있을 수도 있다.
이때, 기차표를 한 번도 검사받지 않는 승객 수의 최솟값과 최댓값을 구하는 프로그램을 작성하시오.
첫째 줄에 N과 K가 주어진다. (2 ≤ N ≤ 1000, 1 ≤ K ≤ 1000)
다음 N개 줄에는 각 역에서 기차에서 내리는 승객의 수와 기차를 타는 승객의 수가 공백으로 구분되어져서 주어진다. (기차가 지나가는 역을 순서대로 주어진다) 모든 숫자는 0보다 크거나 같고, 1000보다 크지 않다.
첫째 줄에 기차표를 한 번도 검사받지 않는 승객 수의 최솟값과 최댓값을 공백으로 구분해서 출력한다.
기차표를 한 번도 검사받지 않는 승객 수의 최솟값과 최댓값을 구하는 것이 목적이다.
최솟값으로 만들기 위해서는 역에서 사람들이 내릴 때 기차표를 검사한 사람이 우선적으로 내리게끔 한다.
그래야 검사받지 않은 승객 수가 최소가 된다.
최댓값을 만들기 위해서는 역에서 사람들이 내릴 때 기차표를 검사하지 않은 사람이 우선적으로 내리게끔 한다.
그래야 검사받지 않은 승객 수가 최대가 된다.
예를 들어 입력이 다음과 같을 때
4 2
0 5
0 5
3 0
7 0
최솟값을 구해 보겠다.
첫 번째 역에서 5명이 탑승했다.
기차표를 검사한다. cp = 5, np = 0;
두 번째 역에서 5명이 탑승했다. cp = 5, np = 5;
세 번째 역에서 3명이 내렸다. 이때 체크한 사람을 내보낸다. cp = 2, np = 5;
2개의 역을 지나쳤기 때문에 기차표를 검사한다. cp = 7, np = 0;
네 번째 역에서 7명이 내렸다. 체크한 사람인 7명을 내보낸다.
그래서 최솟값은 0이 된다.
시간 복잡도는 O(N)이다.
import java.io.*;
import java.util.*;
public class Main {
static int N,K;
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
int[][] stations = new int[N][2];
for(int i=0; i<N; i++) {
StringTokenizer st2 = new StringTokenizer(br.readLine());
stations[i][0] = Integer.parseInt(st2.nextToken()); //내리는 사람
stations[i][1] = Integer.parseInt(st2.nextToken()); //탑승하는 사람
}
System.out.println(answerMin(stations) + " " + answerMax(stations));
}
static int answerMin(int[][] stations) {
int cnt =0; //답
int cp = stations[0][1]; //체크한 사람
int np = 0; //체크하지 않은 사람
int stand = 0;
for(int i=1; i<N; i++) {
int getOff = stations[i][0]; //내리는 사람들
if(getOff <= cp) {
cp -= getOff;
} else {
getOff -= cp;
cp = 0;
np -= getOff;
cnt += getOff;
}
np += stations[i][1];
if(stand + K == i) {
//티켓 검사
stand = i;
cp += np;
np = 0;
}
}
return cnt;
}
static int answerMax(int[][] stations) {
int cnt = 0;
int cp = stations[0][1];
int np = 0;
int stand = 0;
for(int i=1; i<N; i++) {
int getOff = stations[i][0];
if(getOff <= np) {
np -= getOff;
cnt += getOff;
} else {
getOff -= np;
cnt += np;
np = 0;
cp -= getOff;
}
np += stations[i][1];
if(stand + K == i) {
stand = i;
cp += np;
np = 0;
}
}
return cnt;
}
}