https://www.acmicpc.net/problem/8980
문제
아래 그림과 같이 직선 도로상에 왼쪽부터 오른쪽으로 1번부터 차례대로 번호가 붙여진 마을들이 있다. 마을에 있는 물건을 배송하기 위한 트럭 한 대가 있고, 트럭이 있는 본부는 1번 마을 왼쪽에 있다. 이 트럭은 본부에서 출발하여 1번 마을부터 마지막 마을까지 오른쪽으로 가면서 마을에 있는 물건을 배송한다.
각 마을은 배송할 물건들을 박스에 넣어 보내며, 본부에서는 박스를 보내는 마을번호, 박스를 받는 마을번호와 보낼 박스의 개수를 알고 있다. 박스들은 모두 크기가 같다. 트럭에 최대로 실을 수 있는 박스의 개수, 즉 트럭의 용량이 있다. 이 트럭 한대를 이용하여 다음의 조건을 모두 만족하면서 최대한 많은 박스들을 배송하려고 한다.
- 조건 1: 박스를 트럭에 실으면, 이 박스는 받는 마을에서만 내린다.
- 조건 2: 트럭은 지나온 마을로 되돌아가지 않는다.
- 조건 3: 박스들 중 일부만 배송할 수도 있다.
마을의 개수, 트럭의 용량, 박스 정보(보내는 마을번호, 받는 마을번호, 박스 개수)가 주어질 때, 트럭 한 대로 배송할 수 있는 최대 박스 수를 구하는 프로그램을 작성하시오. 단, 받는 마을번호는 보내는 마을번호보다 항상 크다.
예를 들어, 트럭 용량이 40이고 보내는 박스들이 다음 표와 같다고 하자.
보내는 마을받는 마을박스 개수
1 | 2 | 10 |
1 | 3 | 20 |
1 | 4 | 30 |
2 | 3 | 10 |
2 | 4 | 20 |
3 | 4 | 20 |
이들 박스에 대하여 다음과 같이 배송하는 방법을 고려해 보자.
(1) 1번 마을에 도착하면
- 다음과 같이 박스들을 트럭에 싣는다. (1번 마을에서 4번 마을로 보내는 박스는 30개 중 10개를 싣는다.)
보내는 마을받는 마을박스 개수
1 | 2 | 10 |
1 | 3 | 20 |
1 | 4 | 10 |
(2) 2번 마을에 도착하면
- 트럭에 실려진 박스들 중 받는 마을번호가 2인 박스 10개를 내려 배송한다. (이때 트럭에 남아있는 박스는 30개가 된다.)
- 그리고 다음과 같이 박스들을 싣는다. (이때 트럭에 실려 있는 박스는 40개가 된다.)
보내는 마을받는 마을박스 개수
2 | 3 | 10 |
(3) 3번 마을에 도착하면
- 트럭에 실려진 박스들 중 받는 마을번호가 3인 박스 30개를 내려 배송한다. (이때 트럭에 남아있는 박스는 10개가 된다.)
- 그리고 다음과 같이 박스들을 싣는다. (이때 트럭에 실려 있는 박스는 30개가 된다.)
보내는 마을받는 마을박스 개수
3 | 4 | 20 |
(4) 4번 마을에 도착하면
- 받는 마을번호가 4인 박스 30개를 내려 배송한다
위와 같이 배송하면 배송한 전체 박스는 70개이다. 이는 배송할 수 있는 최대 박스 개수이다.
입력
입력의 첫 줄은 마을 수 N과 트럭의 용량 C가 빈칸을 사이에 두고 주어진다. N은 2이상 2,000이하 정수이고, C는 1이상 10,000이하 정수이다. 다음 줄에, 보내는 박스 정보의 개수 M이 주어진다. M은 1이상 10,000이하 정수이다. 다음 M개의 각 줄에 박스를 보내는 마을번호, 박스를 받는 마을번호, 보내는 박스 개수(1이상 10,000이하 정수)를 나타내는 양의 정수가 빈칸을 사이에 두고 주어진다. 박스를 받는 마을번호는 보내는 마을번호보다 크다.
출력
트럭 한 대로 배송할 수 있는 최대 박스 수를 한 줄에 출력한다.
풀이
가장 빨리 도착하는 배송부터!
도착 마을을 기준으로 오름차순으로 정렬을 하고,
그 배송의 시작과 도착사이에서의 트럭 용량을 확인한다. (중간에 내리고 싣고 할 수 있다는 걸 생각하자!)
트럭의 용량이 싣으려고 하는 박스 개수보다 적으면 트럭 용량만큼만 싣는다. (load_box = empty_space)
배송할 박스들을 싣었으니 시작마을부터 도착마을까지 트럭 용량을 업데이트하고
배송한 박스 개수도 업데이트 해준다.
답안코드
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXC ((int)1e4)
#define MAXM ((int)1e4)
int N, C, M;
struct DATA {
int from, to, packages; // 시작마을, 도착마을, 박스 수
};
DATA table[MAXM + 10];
int truck[MAXC + 10];
void InputData() {
cin >> N >> C;
cin >> M;
for (int i = 0; i < M; i++) {
cin >> table[i].from >> table[i].to >> table[i].packages;
}
}
bool comp(DATA a, DATA b) {
return a.to < b.to;
}
int Solve() {
int boxes = 0;
sort(table, table + M, comp); // 도착마을 기준으로 정렬
for (int i = 0; i < M; i++) {
int load_box = table[i].packages; // 일단 보내려고 하는 박스 다 싣으려고 할건데
for (int town = table[i].from; town < table[i].to; town++) { // 시작마을부터 도착마을까지
int empty_space = C - truck[town];
if (load_box > empty_space) { // 트럭 용량이 싣으려고 하는 박스 개수보다 적으면
load_box = empty_space; // 트럭 용량만큼만 싣기
}
}
for (int j = table[i].from; j < table[i].to; j++) { // 시작마을부터 도착마을까지 트럭용량 업데이트
truck[j] += load_box;
}
boxes += load_box; // 배송한 박스 개수 업데이트
}
return boxes;
}
int main() {
int ans = -1;
InputData();
ans = Solve();
cout << ans << endl;
return 0;
}
'Algorithm' 카테고리의 다른 글
[C++] 프로그래머스 Lv.1 크기가 작은 부분 문자열 (0) | 2024.03.03 |
---|---|
[C++] 백준 3078번: 좋은 친구 (0) | 2022.10.17 |
[C++] 백준 2531번: 회전 초밥 (0) | 2022.10.17 |
[C++] 백준 2670번: 연속부분최대곱 (0) | 2022.10.17 |
[C++] 백준 2578번: 빙고 (0) | 2022.10.17 |