www.acmicpc.net/problem/2228

 

2228번: 구간 나누기

N(1≤N≤100)개의 수로 이루어진 1차원 배열이 있다. 이 배열에서 M(1≤M≤⌈(N/2)⌉)개의 구간을 선택해서, 구간에 속한 수들의 총 합이 최대가 되도록 하려 한다. 단, 다음의 조건들이 만족되어야

www.acmicpc.net

이 문제는 조건을 잘 확인해야 합니다.

1. 각 구간은 한 개 이상의 연속된 수들로 이루어진다.

2. 서로 다른 두 구간끼리 겹쳐있거나 인접해 있어서는 안 된다.

3. 정확히 M개의 구간이 있어야 한다. M개 미만이어서는 안 된다

6 2
-1
3
1
2
4
-1

위 예제에서의 답은 {3}과 {2, 4}를 선택하여 9입니다.

 

dp[idx][cnt] = 구간의 시작인덱스가 idx이고 cnt번째 구간일 때의 최댓값>

idx가 구간의 시작점이고, 구간의 끝은 반복문을 통해 구하였습니다.

 

구간의 끝을 구하기 전에 idx번째 수를 선택하지 않을 수도 있기때문에 먼저 구해주었습니다.

idx ~ i의 구간을 골랐으면 다음 구간은 이 구간과 인접해있으면 안되기때문에 i+2를 넘겨주었습니다.

 

정확히 M개를 골랐으면 합의 최댓값을 갱신, 남은 배열에서 M개의 구간을 못 고르는 경우 MIN값을 리턴하였습니다.

 

 

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
#include <iostream>
#include <algorithm>
#define INF 1000000000
using namespace std;
 
int list[101], sum[101], dp[101][51];
int N, M;
 
int func(int idx, int cnt) {
    if (cnt == M) return 0;
    if ((N - idx + 2/ 2 < M - cnt) return -INF;
 
    int &ret = dp[idx][cnt];
    if (ret != -INF) return ret;
    ret = func(idx + 1, cnt);
 
    for (int i = idx; i <= N; i++) {
        ret = max(ret, func(i + 2, cnt + 1+ sum[i] - sum[idx - 1]);
    }
 
    return ret;
}
 
void init() {
    for (int i = 0; i <= N; i++) {
        for (int j = 0; j <= M; j++) {
            dp[i][j] = -INF;
        }
    }
}
 
void input() {
    cin >> N >> M;
    for (int i = 1; i <= N; i++) {
        cin >> list[i];
        sum[i] = sum[i - 1+ list[i];
    }
    init();
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    cout << func(10<< '\n';
 
    return 0;
}
cs

'algorithm > dp' 카테고리의 다른 글

boj 1937 욕심쟁이 판다  (0) 2021.03.28
boj 2201 이친수 찾기  (2) 2021.03.24
boj 1695 팰린드롬 만들기  (0) 2021.03.20
boj 9177 단어 섞기  (0) 2021.03.19
boj 10942 팰린드롬?  (0) 2021.03.12

+ Recent posts