BOJ 백준 13398 : 연속합 2
Updated:
시작하면서
이번 문제는 다이나믹 프로그래밍 문제이다.
문제 이해
해당 문제는 다이나믹 프로그래밍 개념 중 메모이제이션을 사용해서 해결하는 문제이다. 조건 중에 수를 1개 제거할 수도 있고, 제거하지 않아도 되는 조건이 있기 때문에 구간합을 총 2번 구하고, 구한 구간합 중에 가장 큰 값을 답으로 출력한다.
(정수 개수의 범위가 최대 10만개이므로 무식하게 모든 경우를 다 들여다보면 O(n^2)으로 10만*10만 경우가 되어서 시간초과가 발생한다)
- 일반적으로 0~i까지의 구간합 중 가장 큰 값을 [배열1]에 하나씩 쌓아간다.
- 1번에서 쌓아둔 구간값 [배열1]과 쌓아둔 구간 값에서 한 개의 값을 뺐을 때의 구간값을 비교해서 더 큰 값을 [배열2]에 넣어준다.
- [배열1]과 [배열2]를 모두 돌면서 가장 큰 값을 답으로 출력한다.
해결
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
// sync off
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// sync off
vector<int> numbers, continuousSum[2];
int n, result = 0;
cin >> n;
numbers.resize(n);
continuousSum[0].resize(n);
continuousSum[1].resize(n);
for (int i = 0; i < n; i++)
{
cin >> numbers[i];
}
// 1. 일반 구간합
continuousSum[0][0] = numbers[0];
for (int i = 1; i < n; i++)
{
continuousSum[0][i] = max(numbers[i], continuousSum[0][i - 1] + numbers[i]);
}
// 2. 하나를 제외한 구간합
continuousSum[1][0] = numbers[0];
for (int i = 1; i < n; i++)
{
continuousSum[1][i] = max(continuousSum[0][i - 1], continuousSum[1][i - 1] + numbers[i]);
}
// 3. 1/2번 경우 중에 가장 큰 구간합을 찾음
result = continuousSum[0][0];
for (int i = 0; i < n; i++)
{
result = max(continuousSum[0][i], result);
result = max(continuousSum[1][i], result);
}
cout << result << "\n";
return 0;
}
마치며
구간합에 관한 문제를 자주 접하지 않아서 초반에 힘들었다. 검색을 통해 구간합 구하는 방법을 보고 해결할 수 있었다. 구간합을 배우는 좋은 문제!
Leave a comment