mojo's Blog

[백준 11066] 파일 합치기 본문

백준/Dynamic Programming

[백준 11066] 파일 합치기

_mojo_ 2021. 11. 4. 23:41

문제 링크 => 11066번: 파일 합치기 (acmicpc.net)

 

11066번: 파일 합치기

소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본

www.acmicpc.net

 

다이나믹 프로그래밍 문제이다.

 

이 문제는 알고리즘 시간때 배웠던 행렬 곱 연산을 최소로 만드는 그 문제와 비슷해서 한번에 풀렸다.

 

T(i, j) =  파일 i 번째에서 j 번째까지를 하나의 파일로 합칠 때 최소 시간

S(i, j) =  파일 i 번째에서 j 번째까지를 합치는 과정에서 걸리는 최소 시간

 

예를 들어서 20, 50, 30 이 있다고 하자.

 

S(1, 1) = 20, S(2, 2) = 50, S(3, 3) = 30 이고

T(1, 1) = T(2, 2) = T(3, 3) = 0 임을 알 수 있다.

 

S(1, 2) = 20 + 50 = 70, S(2, 3) = 50 + 30 = 80 이고

T(1, 2) = T(1, 1) + T(2, 2) + S(1, 2) = 70, T(2, 3) = T(2, 2) + T(3, 3) + S(2, 3) = 80 임을 알 수 있다.

 

S(1, 3) = S(1, 1) + S(2, 3) = 20 + 80 = 100 이거나             

S(1, 3) = S(1, 2) + S(3, 3) = 70 + 30 = 100 이다.

 

이 경우에는 같지만 i, j의 격차가 커질 수록 달라질 수 있으므로 minimum 값을 잡아줘야 한다.

 

T(1, 3) = T(1, 1) + T(2, 3) + S(1, 3) = 80 + 100 = 180 이거나             

T(1, 3) = T(1, 2) + T(3, 3) + S(1, 3) = 70 + 100 = 170 이다.

 

이 경우에는 170이 더 작으므로 T(1, 3) = 170 즉, 하나의 파일로 합칠 때 최소 시간은 170 이다.

 

위와 같이 노가다를 함으로써 얻어낸 Optimal Substructure는 다음과 같다.

 

 

 

S(i, j) = min(S(i, j), S(i, k) + S(k + 1, j)) (i <= k <= j - 1)

T(i, j) = min(T(i, j), T(i, k) + T(k + 1, j) + S(i, j)) (i <= k <= j - 1)

 

 

 

 

Solution Code

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string>
#include <stdlib.h>

#define INF 100000000

using namespace std;

int solution(int* f, int n) 
{
	int** T, ** S;
	int result;
	
	T = (int**)malloc(sizeof(int*) * (n + 1));
	S = (int**)malloc(sizeof(int*) * (n + 1));
	for (int i = 0; i <= n; i++) {
		T[i] = (int*)malloc(sizeof(int) * (n + 1));
		S[i] = (int*)malloc(sizeof(int) * (n + 1));
	}

	for (int i = 1; i <= n; i++)
		S[i][i] = f[i], T[i][i] = 0;
	for (int gap = 1; gap < n; gap++) {
		for (int i = 1; i <= n - gap; i++) {
			int j = i + gap;
			S[i][j] = T[i][j] = INF;
			for (int k = i; k < j; k++) {
				S[i][j] = min(S[i][j], S[i][k] + S[k + 1][j]);
				T[i][j] = min(T[i][j], T[i][k] + T[k + 1][j] + S[i][j]);
			}
		}
	}
	result = T[1][n];
	
	for (int i = 0; i <= n; i++) {
		free(S[i]);
		free(T[i]);
	}
	free(S);
	free(T);

	return result;
}

void test() 
{
	int n;
	int* f;
	
	cin >> n;
	f = (int*)malloc(sizeof(int) * (n + 1));
	for (int i = 1; i <= n; i++)
		cin >> f[i];
	cout << solution(f, n) << endl;
}

int main(void) {
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

	int t;
	cin >> t;
	while (t--)
		test();

	return 0;
}

 

'백준 > Dynamic Programming' 카테고리의 다른 글

[백준 10942] 팰린드롬?  (0) 2021.11.07
[백준 1958] LCS 3  (0) 2021.11.06
[백준 1915] 가장 큰 정사각형  (0) 2021.11.04
[백준 2565] 전깃줄  (0) 2021.11.04
[백준 11051] 이항계수 2  (0) 2021.11.04
Comments