11066 파일합치기
알고리즘(DP)
1
2
3
4
5
6
1. 긴 한 줄의 파일들을 두조각으로 분리해서 찾는 방식으로 DP를 함
2. 먼저 0, k-1를 넣음
3. (0, k-1)의 파일 크기의 합을 구한 후, (0,0)-(1,k-1), (0, 1)-(2,k-1) ... 로 모든 두 조각을 만든 후, 그 조각의 비용을 구함
-> start == end 일 경우 합치지 않으므로 비용은 0
ex) (0,1) 일 경우, 0 + 0 + file[0] + file[1]
4. 각 조각의 비용은 dp[start][end]에 저장함.
주의점
1
이전 tc의 결과가 dp를 오염시킬 수 있으므로, dp배열은 항상 초기화한다.
코드
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
#include <iostream>
#include <cstring>
#define MAX_FILE 501
using namespace std;
int k, file[MAX_FILE], DP[MAX_FILE][MAX_FILE], fileSum[MAX_FILE][MAX_FILE], output;
int dp(int start, int end);
int min(int a, int b) {
return a < b ? a : b;
}
int main() {
int tc;
cin >> tc;
for (int i = 0; i < tc; i++) {
cin >> k;
for (int j = 0; j < k; j++) {
cin >> file[j];
}
cout << dp(0, k - 1) << endl;
memset(DP, 0, sizeof(DP));
memset(fileSum, 0, sizeof(DP));
}
}
int dp(int start, int end) {
if (start == end)
return 0;
if (DP[start][end] != 0)
return DP[start][end];
int cur = fileSum[start][end];
if (cur == 0) {
for (int i = start; i <= end; i++)
cur += file[i];
fileSum[start][end] = cur;
}
int result = 2000000000;
for (int i = start; i < end; i++) {
result = min(result, dp(start, i) + dp(i + 1, end));
}
//cout << start << "\t" << end << "\t" << result << "\t" << cur <<endl;
return DP[start][end] = result + cur;
}