#문제

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

 

11066번: 파일 합치기

문제 소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본이 들어있는 한 개의 파일을 만든다. 이 과정에서 두 개의 파일을 합쳐서 하나의 임시파일을 만들고, 이 임시파일이나 원래의 파일을 계속 두 개씩 합쳐서 소설의 여러 장들이 연속이 되도록 파일을 합쳐나가고, 최종적으로는 하나의 파일로 합친다. 두 개의 파일을

www.acmicpc.net

 

#작성 코드

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
#include <iostream>
using namespace std;
 
int t, k;
int ch[501];        // 각 챕터별 파일 사이즈 저장. 인덱스 1~k사용 
int d[501][501]; 
int sum[501];
int INF = 987654321;
int main(){
    cin>>t;
    while(t--){
        cin>>k;
        
        for(int i=1; i<=k; i++){
            cin>>ch[i];
            sum[i] = sum[i-1]+ch[i];
        }
        
        for(int i=1; i<k; i++){            // i : 1 ~ k-1
            for(int a=1; a+i<=k; a++){
                int b = a+i;
                d[a][b] = INF;
                
                for(int mid = a; mid<b; mid++){        // mid : a ~ b-1까지 
                    d[a][b] = min(d[a][b], d[a][mid]+d[mid+1][b]+sum[b]-sum[a-1]);
                                                            // ch[a] + ch[a+1] + ... + ch[b]
                }
            }
        }
        cout<<d[1][k]<<'\n'
    }
    return 0;
}
cs

코드2

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
49
50
51
52
53
#include <iostream>
using namespace std;
 
int t, k;
int dp[501][501];
int ch[501];
int sum[501];
int INF = 987654321;
 
int cal(int x, int y){
    if( dp[x][y] != INF ){
        // ch[x] ~ ch[y]까지 합치는 비용 계산된적있다면 return 
        return dp[x][y];
    }
    if( x==y ){
        // ch[x] ~ ch[x] 합치는 비용은 0 
        return dp[x][y] = 0;
    }
    if( x+1==y ){
        // ch[x] ~ ch[x+1] 합치는 비용은 두 파일의 크기 합 
        return dp[x][y] = ch[x]+ch[x+1];
    }
    
    // 어느 부분을 기준으로 이 구간을 두 부분으로 나누는 것이 좋을까
    // ch[x]~ch[mid] + ch[mid+1]~ch[y] 합치는 비용 최솟값 업데이트. 
    for(int mid=x; mid<y; mid++){
        int leftmin = cal(x, mid);
        int rightmin = cal(mid+1, y);
        dp[x][y] = min(dp[x][y], leftmin+rightmin);
    }
    return dp[x][y] += sum[y]-sum[x-1];
}
 
int main(){
    cin>>t;
    while(t--){
        cin>>k;
        for(int i=1; i<=k; i++){
            cin>>ch[i];
            sum[i] = sum[i-1]+ch[i];        // ~ch[i]까지의 누적합 sum[i]에 저장 
        }
        
        // dp[][]를 모두 INF로 초기화. 
        for(int i=1; i<=k; i++){
            for(int j=1; j<=k; j++){
                dp[i][j] = INF;
            }
        }
        
        cout<<cal(1, k)<<'\n';
    }
    return 0;
}
cs

##

d[i][j] : ch[i] ~ ch[j] 까지 합칠 때 최소 cost 저장.

어렵다... 많이 많이 복습하자

https://js1jj2sk3.tistory.com/3 참고!!

https://kyunstudio.tistory.com/75 참고

https://www.crocus.co.kr/1073 참고

https://boogalle91-cs.tistory.com/32

 

11066 파일 합치기[DP]

S/W 엔지니어를 포기할 까 고민하게 만든 문제였다. 결국 많이 풀어봐야 할 것 같다,, DP문제를 풀 때, 습관적? 고정관념적으로 DP[n] = DP[n-1] + DP[n-2] 처럼 매우 1차원적으로 점진적으로 값이 (오른쪽으로)..

boogalle91-cs.tistory.com

왜 ch[x] + ... ch[y]까지를 더하는지 이해가 안돼서 자료 찾아보는 중..

 

더보기

코드2에 대해서 어떻게 동작하는지 보기 위해 추적한 노트.

dp[1][4]는 두 개씩 묶여서 최소 cost가 되도록 ch[1]~ch[4]까지 합한 cost.

'BOJ' 카테고리의 다른 글

BOJ 11057번 :: 오르막 수  (0) 2020.01.05
BOJ 9095번 :: 1, 2, 3 더하기  (0) 2020.01.05
BOJ 6549번 :: 히스토그램에서 가장 큰 직사각형  (0) 2020.01.04
BOJ 1021번 :: 회전하는 큐  (0) 2020.01.03
BOJ 1300번 :: K번째 수  (0) 2020.01.03

+ Recent posts