[백준 11066][파이썬] 파일 합치기 (dp 알고리즘)

2023. 3. 15. 12:00·백준 알고리즘/dp
728x90

https://www.acmicpc.net/problem/11066

 

11066번: 파일 합치기

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

www.acmicpc.net

dp를 활용하여 삼중 반복문을 사용하여 푸는 문제이다.

 

dp[x][y]는 다음과 같이 정의한다.

 

인덱스 x 파일부터 인덱스 y 파일까지 하나의 파일로 합치는데 필요한 최소비용

 

이를 이용하여 dp 알고리즘을 적용하면 된다.

 

가장 먼저 x와 y가 동일한 경우를 보자.

 

다음과 같이 파일들의 크기를 나열할 때

15
1 21 3 4 5 35 5 4 3 5 98 21 14 17 32

dp[0][0], dp[1][1] ... 과 같이 x와 y의 값이 동일하다면 하나의 파일을 의미하고 이미 하나의 파일이기 때문에 합칠 필요가 없다.

 

그렇기에 x와 y가 같은 위치의 값은 모두 0이다.

 

    for i in range(n):
        dp[i][i] = 0 #길이가 1인 것의 최소 비용

이 다음부터 dp 알고리즘을 적용하는데 상당히 까다롭다.

 

위처럼 15가지의 파일의 크기가 나열되어있을 때 언뜻 살펴보더라도 무수히 많은 경우의 수가 보인다.

 

다행히도 파일들의 개수는 500을 넘지 않는다.

 

문제의 제한 시간은 2초, 파이썬에서 1억번의 연산을 할 때 1초가 걸리는 것을 감안하면 O(N^3)까지는 시간 초과가 발생하지 않는다.

 

현재까지 길이가 1인 경우는 모두 구한 상황이다.

 

이제부터는 길이가 2인 경우, 3인 경우.. n인 경우까지 모두 구할 차례이다.

 

길이가 2인 경우를 생각해보면 두 개의 숫자가 합쳐지는 1가지 경우밖에 존재하지 않는다.

 

즉 dp[x][x+1]의 경우 둘을 더하면 된다.

 

길이가 3인 경우 다음과 같이 2가지 경우가 존재한다.

문제에서 주어진 길이는 15. 우리는 길이가 2, 3인 모든 범위에 대하여 최소 비용을 구한다.

 

이제 길이가 15인 경우를 생각해보면서 공통적으로 적용할 알고리즘을 생각해야한다.

 

우리는 길이를 증가시켜가면서 최소 비용을 구해왔기 때문에 길이가 10인 경우를 구할 때는 모든 범위에 대해서 길이가 1~14인 최소 비용을 알고있다.

 

즉 다음과 같이 반복을 하면 된다.

dp[1][1]값과 dp[2][15]의 합을 구하고 dp[1][2]값과 dp[3][15] 합을 구하고... 이러한 과정을 반복해서 가장 작은 값을 구하면 된다.

 

그런데 dp[1][1] + dp[2][15]의 값은 한 페이지를 만들 때의 최솟값이 아닌 두 페이지를 만들 때의 최솟값이다.

 

그리고 두 페이지를 합칠 때의 비용은 1에서 15까지의 모든 비용의 합을 더한 값이다.

 

즉 정확히는 dp[1][1] + dp[2][15] + sum(arr[1] ~ arr[15]) 이렇게 해당 범위의 모든 값을 더해주는 과정이 필요하다.

 

<최종 코드>

import sys
input=sys.stdin.readline
t=int(input())
for _ in range(t):
    n=int(input())
    arr=list(map(int, input().split()))
    subtotal = [0]*(n+1)
    subtotal[0]=0
    for i in range(1, n+1): #누저합 구하기
        subtotal[i]=arr[i-1]
        subtotal[i]+=subtotal[i-1]
    dp=[ 
        [1e9]*n
        for _ in range(n)
    ]
    for i in range(n):
        dp[i][i] = 0 #길이가 1인 것의 최소 비용
    
    for i in range(2, n+1): #길이
        for j in range(n-i+1): #시작 인덱스
            for k in range(j, j+i-1): #하나한씩 돌음
                dp[j][j+i-1] = min(dp[j][j+i-1], dp[j][k]+dp[k+1][j+i-1]+subtotal[j+i]-subtotal[j]) 
    
    print(dp[0][n-1])
728x90

'백준 알고리즘 > dp' 카테고리의 다른 글

[백준 15486][JAVA] 퇴사 2  (1) 2025.02.15
[백준 9251][파이썬] LCS (최장 공통 부분 수열)  (0) 2023.03.18
[백준 2839][파이썬] 설탕 배달  (0) 2023.01.23
[백준 1699][파이썬] 제곱수의 합  (0) 2023.01.14
[백준 1912][파이썬] 연속 합  (0) 2023.01.13
'백준 알고리즘/dp' 카테고리의 다른 글
  • [백준 15486][JAVA] 퇴사 2
  • [백준 9251][파이썬] LCS (최장 공통 부분 수열)
  • [백준 2839][파이썬] 설탕 배달
  • [백준 1699][파이썬] 제곱수의 합
웅대
웅대
알고리즘과 백엔드를 중심으로 열심히 공부 중입니다! 같이 소통하며 공부해요!
    250x250
  • 웅대
    웅대 개발 블로그
    웅대
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 백준 알고리즘
        • dp
        • 문자열
        • 정렬
        • 스택
        • 브루트 포스
        • 이진 탐색
        • 정리
        • 우선순위 큐
        • 자료구조
        • 그래프
        • 기타
        • 그리디
      • 컴퓨터 언어
        • Kotlin
        • Python
        • C#
      • 공부
        • Database
        • Android Studio
        • Algorithm
        • 컴퓨터 구조론
        • Spring
        • lombok
        • AWS
        • Network
        • OS
        • Git & GitHub
        • AI
        • Computer Vision
        • 보안
        • Nginx
        • 프론트
        • express
        • GCP
        • grokking concurrency
        • DevOps
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    스프링 OAuth2
    nn.RNN
    파이썬
    스택
    Merge
    RNN
    Vector Store
    bfs
    다익스트라
    ChatPromptTemplate
    influxDB CLI
    codetree
    AWS Lambda
    openvidu 배포
    embedding
    binary search
    ci/cd
    푸쉬 알람
    parametric search
    code tree
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
웅대
[백준 11066][파이썬] 파일 합치기 (dp 알고리즘)
상단으로

티스토리툴바