[C++] 백준/Gold/11066. 파일 합치기

2025. 4. 10. 21:43·C++/Algorithm

 

파일 합치기 (백준 11066번)

문제 개요

여러 파일을 하나의 파일로 합칠 때, 두 파일을 합치는 비용은 두 파일의 크기의 합이다.
여러 개의 파일을 주어진 순서대로 합칠 때,
전체 합치는 비용을 최소화하는 합치는 순서를 찾는 문제이다.

접근 방법: 동적 계획법 (DP)

문제는 구간 DP 문제의 대표적인 예제로,
파일 $ A_i $의 크기를 배열 $ \text{arr}[i] $로 두면,
구간 $[i, j]$에 있는 파일들을 합치는 최소 비용 $ dp[i][j] $는 다음 점화식으로 구할 수 있다.

1. 누적 합 (Prefix Sum)

연속된 파일 크기의 합을 빠르게 계산하기 위해,
누적 합 배열 $ \text{subtotal} $을 사용한다.
$$
\text{subtotal}[k] = \sum_{l=0}^{k-1} \text{arr}[l]
$$
따라서, 구간 $[i,j]$의 파일 크기 합은 다음과 같다.
$$
\text{sum}(i,j) = \text{subtotal}[j+1] - \text{subtotal}[i]
$$

2. 동적 계획법 점화식

구간 $[i,j]$의 파일들을 합치는 최소 비용 $ dp[i][j] $는 다음과 같이 정의한다.

  • 기저 조건:
    단일 파일인 경우, 비용은 0
    $$
    dp[i][i] = 0 \quad \text{for all } i
    $$
  • 점화식:
    구간 $[i,j]$를 합칠 때, 중간 분할점 $ k $ $(i \le k < j)$를 기준으로
    양쪽 구간의 합치는 최소 비용과, 두 구간을 합칠 때의 비용(두 구간의 크기의 합)을 더한 값 중 최소값으로 결정된다.
    $$
    dp[i][j] = \min_{i \le k < j} \left{ dp[i][k] + dp[k+1][j] + \text{sum}(i,j) \right}
    $$
    여기서 $\text{sum}(i,j) = \text{subtotal}[j+1] - \text{subtotal}[i]$이다.

코드 설명

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios_base::sync_with_stdio(false); 
    cin.tie(nullptr);
    int t;
    cin >> t;

    while (t--)
    {
        int n;
        cin >> n;

        vector<int> arr(n);
        for (int i = 0; i < n; ++i)
        {
            cin >> arr[i];
        }

        // 누적 합 배열: subtotal[i] = arr[0] + arr[1] + ... + arr[i-1]
        vector<int> subtotal(n + 1, 0);
        for (int i = 1; i <= n; ++i)
        {
            subtotal[i] = subtotal[i - 1] + arr[i - 1];
        }

        // dp[i][j] : 구간 [i, j]의 파일들을 합치는 최소 비용.
        // 초기값: 같은 위치는 파일 하나이므로 비용 0.
        vector<vector<int>> dp(n, vector<int>(n, 1e9));
        for (int i = 0; i < n; ++i)
        {
            dp[i][i] = 0;
        }

        // 길이가 2부터 n인 구간에 대해 비용 계산
        for (int len = 2; len <= n; ++len)
        {
            for (int start = 0; start <= n - len; ++start)
            {
                int end = start + len - 1;
                // 중간 분할점 mid를 통해, 두 부분 구간을 합치는 경우를 고려
                for (int mid = start; mid < end; ++mid)
                {
                    dp[start][end] = min(dp[start][end],
                        dp[start][mid] + dp[mid + 1][end] + (subtotal[end + 1] - subtotal[start]));
                }
            }
        }

        cout << dp[0][n - 1] << '\n';
    }
}

'C++ > Algorithm' 카테고리의 다른 글

[C++] 백준/Gold/4179. 불!  (0) 2025.04.24
[C++] 백준/Gold/15685. 드래곤 커브  (0) 2025.04.23
[C++] 백준/Gold/10986. 나머지 합  (0) 2025.04.09
[C++] 백준/Silver/1024. 수열의 합  (0) 2025.04.08
[C++] 백준/Silver/15549. if  (0) 2025.04.04
'C++/Algorithm' 카테고리의 다른 글
  • [C++] 백준/Gold/4179. 불!
  • [C++] 백준/Gold/15685. 드래곤 커브
  • [C++] 백준/Gold/10986. 나머지 합
  • [C++] 백준/Silver/1024. 수열의 합
돼지표
돼지표
https://github.com/wkdgns135
  • 돼지표
    돼지표 개발 스토리
    돼지표
  • 전체
    오늘
    어제
    • 분류 전체보기 (99)
      • C++ (58)
        • Algorithm (52)
      • Python (1)
      • Machine Learning (2)
      • Computer Graphics (4)
        • Curly Hair Simulation (2)
      • GPU Programming (11)
        • CUDA basic (7)
        • CUDA fluidsGL (4)
      • Unreal 5 (20)
        • Troubleshooting (4)
        • FPS Shooting (5)
        • Study (9)
        • EOS (1)
      • Computer Science (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    Algorithm
    unreal 5
    구현
    CS
    CUDA
    dp
    그래프 탐색
    아이작 맵 생성
    UE5
    그리디 알고리즘
    자료 구조
    FPS
    GPU Programming
    C++
    수학
    BFS
    OpenGL
    위상 정렬
    Rendering Pipeline
    Fluid Simulation
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
돼지표
[C++] 백준/Gold/11066. 파일 합치기
상단으로

티스토리툴바