메모리: 20996 KB, 시간: 324 ms
그리디 알고리즘, 정렬
2025년 3월 7일 13:55:58
아래 그림과 같이 직선 도로상에 왼쪽부터 오른쪽으로 1번부터 차례대로 번호가 붙여진 마을들이 있다. 마을에 있는 물건을 배송하기 위한 트럭 한 대가 있고, 트럭이 있는 본부는 1번 마을 왼쪽에 있다. 이 트럭은 본부에서 출발하여 1번 마을부터 마지막 마을까지 오른쪽으로 가면서 마을에 있는 물건을 배송한다.
각 마을은 배송할 물건들을 박스에 넣어 보내며, 본부에서는 박스를 보내는 마을번호, 박스를 받는 마을번호와 보낼 박스의 개수를 알고 있다. 박스들은 모두 크기가 같다. 트럭에 최대로 실을 수 있는 박스의 개수, 즉 트럭의 용량이 있다. 이 트럭 한대를 이용하여 다음의 조건을 모두 만족하면서 최대한 많은 박스들을 배송하려고 한다.
마을의 개수, 트럭의 용량, 박스 정보(보내는 마을번호, 받는 마을번호, 박스 개수)가 주어질 때, 트럭 한 대로 배송할 수 있는 최대 박스 수를 구하는 프로그램을 작성하시오. 단, 받는 마을번호는 보내는 마을번호보다 항상 크다.
예를 들어, 트럭 용량이 40이고 보내는 박스들이 다음 표와 같다고 하자.
| 보내는 마을 | 받는 마을 | 박스 개수 |
|---|---|---|
| 1 | 2 | 10 |
| 1 | 3 | 20 |
| 1 | 4 | 30 |
| 2 | 3 | 10 |
| 2 | 4 | 20 |
| 3 | 4 | 20 |
이들 박스에 대하여 다음과 같이 배송하는 방법을 고려해 보자.
(1) 1번 마을에 도착하면
| 보내는 마을 | 받는 마을 | 박스 개수 |
|---|---|---|
| 1 | 2 | 10 |
| 1 | 3 | 20 |
| 1 | 4 | 10 |
(2) 2번 마을에 도착하면
| 보내는 마을 | 받는 마을 | 박스 개수 |
|---|---|---|
| 2 | 3 | 10 |
(3) 3번 마을에 도착하면
| 보내는 마을 | 받는 마을 | 박스 개수 |
|---|---|---|
| 3 | 4 | 20 |
(4) 4번 마을에 도착하면
위와 같이 배송하면 배송한 전체 박스는 70개이다. 이는 배송할 수 있는 최대 박스 개수이다.
입력의 첫 줄은 마을 수 N과 트럭의 용량 C가 빈칸을 사이에 두고 주어진다. N은 2이상 2,000이하 정수이고, C는 1이상 10,000이하 정수이다. 다음 줄에, 보내는 박스 정보의 개수 M이 주어진다. M은 1이상 10,000이하 정수이다. 다음 M개의 각 줄에 박스를 보내는 마을번호, 박스를 받는 마을번호, 보내는 박스 개수(1이상 10,000이하 정수)를 나타내는 양의 정수가 빈칸을 사이에 두고 주어진다. 박스를 받는 마을번호는 보내는 마을번호보다 크다.
트럭 한 대로 배송할 수 있는 최대 박스 수를 한 줄에 출력한다.
문제풀이

코드
/**
* Author: nowalex322, Kim HyeonJae
*/
import java.io.*;
import java.util.*;
public class Main {
class Package implements Comparable<Package> {
int from, to, weight;
public Package(int from, int to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
@Override
public int compareTo(Package o) {
if (this.to == o.to) return this.from - o.from;
return this.to - o.to;
}
}
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static int N, C, M, from, to, weight, res;
static Package[] packages;
public static void main(String[] args) throws Exception {
new Main().solution();
}
public void solution() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
// br = new BufferedReader(new InputStreamReader(new FileInputStream("src/main/java/BOJ_8980_택배/input.txt")));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
M = Integer.parseInt(br.readLine());
packages = new Package[M + 1];
for (int i = 1; i <= M; i++) {
st = new StringTokenizer(br.readLine());
from = Integer.parseInt(st.nextToken());
to = Integer.parseInt(st.nextToken());
weight = Integer.parseInt(st.nextToken());
packages[i] = new Package(from, to, weight);
}
Arrays.sort(packages, 1, M + 1);
int[] availableC = new int[N+1];
Arrays.fill(availableC, C);
for (int i = 1; i <= M; i++) {
Package currP = packages[i];
int minC = C;
// 그 구간에서 옮길 수 있는 양
for(int j= currP.from; j< currP.to; j++) {
minC = Math.min(minC, availableC[j]);
}
// 배송할 양 결정 (그 구간에서 옮길 수 있는 최소값 or 현재 패키지 박스양 중 최솟값)
int selectedC = Math.min(currP.weight, minC);
if(selectedC > 0){
for(int k= currP.from; k<currP.to; k++) {
availableC[k] -= selectedC;
}
res += selectedC;
}
}
System.out.println(res);
bw.flush();
bw.close();
br.close();
}
}