-
백준 2228번 : 구간 나누기알고리즘 공부 2020. 5. 5. 16:35
험멈멈... 왜 어렵지....? 어려울 것 같은 문제가 아니었는데 어렵다! 이럴 수가... 난 바보인가바...
풀이
dp를 잘 정의해보자.
dp[n][m] : 첫 번째부터 n번째까지의 수들 중에서 m개의 구간을 선택했을 때 구간 합의 최댓값
n번째까지의 수 중에서 n번째 숫자가 구간에 포함되지 않았을 경우
이 경우 n번째 숫자가 없는 것과 마찬가지다.
dp [n][m] = dp [n-1][m]
n번째까지의 수 중에서 n번째 숫자가 구간에 포함되었을 경우
이 경우 n번째 숫자는 마지막 구간, 즉 m번째 구간에 포함되었을 것이다. m번째 구간이 k번째 수부터 n번째 수까지라고 가정해보자. m-1번째 구간은 m번째 구간과 인접할 수 없으므로 k-1번째 수는 사용할 수 없다. 따라서 k-2번째 수까지만 사용해서 m-1개의 구간을 만들어야 한다.
dp [n][m] = dp [k-2][m-1] + sum(k, n)
하지만 m번째 구간이 어디서부터 시작하는지 정확히 알 수 없으므로 for문을 돌려서 최댓값을 구해야 한다.
#include <iostream> using namespace std; int n, m; bool visit[102][52]; int dp[102][52]; int sum[102]; int areaSum(int num, int area) { if(area == 0) return 0; if(num < 2*area-1) return -987654321; if(visit[num][area]) return dp[num][area]; visit[num][area] = true; dp[num][area] = areaSum(num-1, area); for(int i = num; i >= 1; i--) { dp[num][area] = max(dp[num][area], sum[num] - sum[i-1] + areaSum(i-2, area-1)); } return dp[num][area]; } int main() { ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> n >> m; int seq; for(int i = 1; i <= n; i++) { cin >> seq; sum[i] = sum[i-1] + seq; } cout << areaSum(n, m); return 0; }
'알고리즘 공부' 카테고리의 다른 글
백준 2666번 : 벽장문의 이동 (0) 2020.05.07 백준 2229번 : 조 짜기 (0) 2020.05.07 백준 1720번 : 타일 코드 (1) 2020.05.04 백준 1695번 : 팰린드롬 만들기 (0) 2020.05.03 백준 2662번 : 기업투자 (0) 2020.05.02