📦11066: 파일 합치기
[알고리즘 풀이] 강동규
Reviewed by Kade Kang (devkade12@gmail.com)
Reviewed:: 2024-02-19
문제 확인하기
풀이
- Matrix_calcuation-11049 문제와 거의 동일한 문제이다.
- 이 문제에서 주의할 점은 임시파일을 만들면서 중복적으로 발생하는 비용이다.
- C1, C2, C3, C4 = 40, 30, 30, 50 을 예로 들어보자.
- 문제대로 합쳐 보면
- C2 + C3 = 60 = X1
- X1 + C1 = 100 = X2
- X2 + C4 = 150 = X3
- 최종 = X1(C2 + C3) + X2(C1 + C2 + C3) + X4(C1 + C2 + C3 + C4)
- 때문에 해당 부분에 집중해서 변형해준다.
- 3중 for문은 Matrix_calcuation-11049 의 풀이를 참고하면 된다.
풀이
-
이 문제는 1시간을 고민해도 전혀 갈피를 잡지 못하겠어서 결국 https://cocoon1787.tistory.com/318의 풀이를 참고했다. 확실히 DP 문제에 약하다고 느껴진다.
-
dp[n][m] 는 n 에서 m 까지의 범위를 행렬 연산했음을 의미한다.
-
3중 for 문을 사용하여 행렬 연산의 범위, 시작 지점, 범위 연산을 지정해 계산한다.
-
i 는 행렬의 범위를 지정한다. i = 2 일 경우, dp[n][m] 에서 m-n, n과 m 사이의 거리, 차이가 2라는 뜻이다.
-
j 는 행렬의 시작 지점을 말한다. j = 3, i = 2 인 경우 dp[3][5] 로 3에서 시작해서 5번째까지의 행렬을 구한다.
-
mid 는 범위 안에서의 실질적인 연산을 진행한다. dp[3][10] 을 구한다고 하면 mid 는 3~10 의 값이고, 반복문을 돌면서 dp[3][3], dp[3][4], … 를 구한다.
-
최종적으로는 dp[1][N] 을 구하면 1~N 까지의 행렬 연산의 최솟값을 구할 수 있다.
-
혼자 생각할 때 dp로 느낌이 들기는 했지만 어떻게 풀어야 할지 감이 오지 않았다. 해당 문제를 풀이하는 방식이 이해를 하니까 끄덕일 수 있었지만 체득이 필요할 것 같다.
-
#include <iostream>
#define endl '\n'
using namespace std;
int T, N;
int Info[501][2];
int dp[501][501];
void Input(){
cin >> N;
for(int i=1; i<=N; i++) {
cin >> Info[i][0];
Info[i][1] = Info[i-1][1] + Info[i][0];
}
}
void Solution(){
while(T--){
Input();
for(int i=1; i<N; i++){
for(int j=1; i+j<=N; j++){
dp[j][i+j] = INT32_MAX;
for(int k=j; k<=i+j; k++){
dp[j][i+j] = min(dp[j][i+j], dp[j][k] + dp[k+1][i+j] + Info[i+j][1] - Info[j-1][1]);
}
}
}
cout << dp[1][N] << endl;
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin >> T;
Solution();
return 0;
}