11066번: 파일 합치기
소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본
www.acmicpc.net
파일을 합칠 수 있는데 합치는데 드는 비용의 누적 합 중 최소가 되는 값이 정답이 된다.
재귀적으로 접근하면 그나마 쉽게 해 볼 수 있는데 그래도 어렵다..
위 사진처럼 진행하는데
임시파일이나 원래의 파일을 계속 두 개씩 합쳐서 소설의 여러 장들이 연속이 되도록 파일을 합쳐나가고, 최종적으로는 하나의 파일로 합친다
연속이 되야 하기 때문에 따로 정렬이나 부분을 나누어서 접근하면 틀린다.
d [i][j]를 i ~ j 구간의 최소합이라고 하면
1부터 n 까지의 구간합 중 최소가 정답이 된다.
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
|
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 1e9;
int pSum[501], d[501][501];
int t, n, a[501];
int f(int s, int e) {
if (s == e) return 0;
if (s + 1 == e) return d[s][e] = a[s] + a[e];
if (d[s][e] != inf) return d[s][e];
for (int i = s; i <= e; ++i)
d[s][e] = min(d[s][e], f(s, i) + f(i + 1, e));
return d[s][e] += pSum[e] - pSum[s - 1];
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> t;
while (t--) {
fill(&d[0][0], &d[500][501], inf);
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i], pSum[i] = pSum[i - 1] + a[i];
cout << f(1, n) << '\n';
}
return 0;
}
|
cs |
우선 2개로 나뉠 때까지 쪼개 주고, 2개로 나뉘었다면 그 두 합을 더해준다.
이후 반복문을 통해 mid값을 s와 e 사이에서 돌려보면서 그중에서 최소가 되는 값을 찾는다
우리가 원하는 값은 모든 누적값이기 때문에 return 할 때에 구간 합을 더해줘서 반환해줘야 한다.
'BOJ' 카테고리의 다른 글
BOJ 5052 전화번호 목록 (0) | 2020.12.10 |
---|---|
BOJ 5014 스타트링크 (0) | 2020.12.10 |
BOJ 10164 격자상의 경로 (0) | 2020.12.03 |
BOJ 6087 레이저 통신 (0) | 2020.12.02 |
BOJ 14442 벽 부수고 이동하기 2 (0) | 2020.12.02 |