문제 : https://www.acmicpc.net/problem/13335
13335번: 트럭
입력 데이터는 표준입력을 사용한다. 입력은 두 줄로 이루어진다. 입력의 첫 번째 줄에는 세 개의 정수 n (1 ≤ n ≤ 1,000) , w (1 ≤ w ≤ 100) and L (10 ≤ L ≤ 1,000)이 주어지는데, n은 다리를 건너는 트
www.acmicpc.net
문제 파악하기
N개의 트럭이 다리를 건너는데 필요한 최소 시간을 구하는 문제입니다. 트럭의 순서는 바꿀 수 없으며, 모든 트럭은 다리를 건너는데 W만큼의 시간이 걸립니다. 최대 하중인 L을 넘지 않는 선에서 모든 트럭이 다리를 건너는데 필요한 최소 시간을 구하기 위해서는 현재 다리를 건너고 있는 트럭의 총 하중을 고려하여 직접 시뮬레이션 할 수 있습니다. 또는 트럭이 다리를 모두 건너는데 필요한 시간에 초점을 맞춰서 구할 수도 있습니다.
문제 해결하기
가장 간단한 방법은 시간을 하나씩 증가시키면서 시뮬레이션 하는 알고리즘이 있습니다. 이 알고리즘은 트럭의 개수가 많아지거나 시간이 오래 걸릴수록 효율이 떨어지게 됩니다. 하지만 이 문제에서는 트럭의 개수도 작으며, 다리의 길이도 작기에 충분히 모든 과정을 시뮬레이션할 수 있습니다.
또다른 방법은 모든 과정을 시뮬레이션 하지 않고 특정 과정만 시뮬레이션 하는 방법이 있습니다. 사실 생각해보면 트럭이 다리 위에서 움직이는 과정은 시뮬레이션할 필요가 없습니다. 트럭이 움직이는 과정 중 중요한 순간은 다리에 올라가는 순간과 내려가는 순간입니다. 따라서, 우리는 트럭이 언제 다리에 올라가서 내려가는지를 시간 변수(curT)에 기록하면 충분히 문제를 해결할 수 있습니다.
그럼 언제 트럭이 다리에 올라가는지 알 수 있을까요? 트럭이 다리에 올라가는 경우의 수는 총 2가지입니다. 첫 번째, 다리의 하중이 여유로운 경우입니다. 이 경우에는 그냥 다리에 올라가면 되며, 시간 변수의 값(curT)을 1 증가시켜 주면 됩니다. 두 번째, 다리의 하중이 여유롭지 못한 경우입니다. 이 경우에는 이미 올라간 트럭들을 빼주어야 하며, 이 때에 나가는 트럭의 시간들을 확인할 필요가 있습니다. 내려가는 트럭들이 현재 시간보다 먼저 내려갈 수도 있기 때문에 내려가는 트럭들의 시간(tmpT)와 현재 시간(curT+1) 중 더 큰 값을 저장해주어야 합니다.
이렇게 올라가는 현재 시간을 구했다면 내려가는 시간은 금방 구할 수 있습니다. 현재 시간(curT)에서 다리의 길이(W)만큼 더해주면 됩니다. 이렇게 올라가는 시간과 내려가는 시간을 구하고, 트럭들을 큐를 활용하여 처리하면 어렵지 않게 해결할 수 있습니다.
소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#import <stdio.h>
#import <queue>
#import <vector>
#import <utility>
#define PAIR pair<int, int>
using namespace std;
int N, W, L, t, w;
vector< int > inp;
int curW, tmpT, curT;
queue< PAIR > q;
int main() {
// input
scanf("%d %d %d", &N, &W, &L);
for(int i=0;i<N;i++) {
scanf("%d", &t);
inp.push_back(t);
}
// sv
curT = -1;
for(int i=0;i<N;i++) {
// 트럭 바로 건너기
if(curW+inp[i] <= L) curT++;
else {
// 다리에서 트럭 빼기
while(!q.empty() and curW+inp[i]>L) {
w = q.front().first;
tmpT = q.front().second;
q.pop();
curW -= w;
}
curT = max( curT+1, tmpT );
}
q.push({inp[i], curT+W});
curW += inp[i];
}
// 마지막 트럭의 끝나는 시간
printf("%d", curT+W+1);
}
|
cs |
후기
직접 시뮬레이션 돌리지 않으니 알고리즘을 떠올리기 귀찮은 문제였습니다. 예외 케이스도 종종 생겨서 생각보다 오래 걸린 문제로, 다리의 길이가 좀 더 길어지면 문제가 더 재미있지 않을까 생각이 듭니다.
'문제 노트 > 백준' 카테고리의 다른 글
Two Machines( BOJ 17528 ) (1) | 2023.06.04 |
---|---|
방 청소( BOJ 9938 ) (0) | 2023.05.18 |
보안 업체( BOJ 9938 ) (0) | 2023.05.05 |
소가 길을 건너간 이유( BOJ 14469 ) (0) | 2023.05.05 |
What's Up With Gravity( BOJ 5827 ) (0) | 2022.10.03 |