[Silver II] 연속합 - 1912
성능 요약
메모리: 2928 KB, 시간: 8 ms
분류
다이나믹 프로그래밍
문제 설명
n개의 정수로 이루어진 임의의 수열이 주어진다. 우리는 이 중 연속된 몇 개의 수를 선택해서 구할 수 있는 합 중 가장 큰 합을 구하려고 한다. 단, 수는 한 개 이상 선택해야 한다.
예를 들어서 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 이라는 수열이 주어졌다고 하자. 여기서 정답은 12+21인 33이 정답이 된다.
입력
첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.
출력
첫째 줄에 답을 출력한다.
풀이
- 값이 모두 음수일때와 섞여있을때를 flag를 사용해 나누어 계산했다.
- 값이 양수일때 sum에 값을 더하고, 음수가 나올때 dp에 값을 넣었다.
- sum이 0보다 작아질 경우에는 0으로 초기화 후 그 다음 연산부터 시작한다.
- dp에 들어간 값을 오름차순으로 정렬하고 dp[0] 값을 가져온다.
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
54
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int arr[100001];
vector<int> Dp;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
vector<int> Dp;
int n;
cin >> n;
int sum = 0;
int m_max = -1001;
bool flag = false;
for (int i = 0; i < n; i++) {
cin >> arr[i];
if (arr[i] > 0&&!flag) {
flag = true;
sum = 0;
}
else if(!flag)
{
if (m_max < arr[i])
m_max = arr[i];
}
if (flag) {
if (arr[i] > 0)
sum += arr[i];
else if (arr[i] <= 0) {
Dp.push_back(sum);
sum += arr[i];
if (sum < 0)
sum = 0;
}
if (i == n - 1)
Dp.push_back(sum);
}
}
if (flag)
{
sort(Dp.begin(), Dp.end(),greater<int>());
cout << Dp[0];
}
else
cout << m_max;
}
Dp 활용 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
int main()
{
int n,res,a[100001],dp[100001];
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
res=a[1];
dp[1]=a[1];
for(int i=2;i<=n;i++)
{
dp[i]=max(dp[i-1]+a[i],a[i]);
res=max(dp[i],res);
}
cout<<res;
}