알고리즘 공부
백준 2228번 : 구간 나누기
EQ1
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;
}