https://www.acmicpc.net/problem/1912
1912번: 연속합
첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.
www.acmicpc.net
dp 문제이다. 연속된 숫자의 합을 구하는 문제이기 때문에 dp[i]는 i로 시작하는 연속합의 최대값이라 하였을때 a[i]에서 a[i+1]을 더한값과 a[i]값을 비교하여 더 큰값을 dp[i]에 저장해 주었다. 배열 b[i]를 사용해서 수연산을 최소화 하였다.
#include <iostream>
#include <algorithm>
using namespace std;
int a[100001] = { 0, };
int b[100001] = { 0, };
int dp[100001] = { 0, };
int main(int argc, char* argv[])
{
int n;
cin >> n;
int ans = -1001;
for (int i = 1; i <= n; i++) {
cin >> a[i];
dp[i] = b[i] = a[i];
}
for (int i = 1; i <= n; i++) {
for (int j = i + 1;j <= n;j++) {
b[i] += a[j];
if (dp[i] < b[i])
dp[i] = b[i];
}
if (ans < dp[i])
ans = dp[i];
}
cout << ans << "\n";
return 0;
}
시간초과가 발생하였고 dp를 제대로 사용하지 못하고 있음을 깨달았다. 굳이 b[i]를 사용하지 않고 dp[i]는 i로 끝나는 연속합의 최대값으로 생각해보았다.
#include <iostream>
#include <algorithm>
using namespace std;
int a[100001] = { 0, };
int dp[100001] = { 0, };
#include <iostream>
#include <algorithm>
using namespace std;
int a[100001] = { 0, };
int dp[100001] = { 0, };
int main(int argc, char* argv[])
{
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
int ans = a[0];
dp[0] = a[0];
for (int i = 1; i < n; ++i) {
dp[i] = max(dp[i - 1] + a[i], a[i]);
ans = max(dp[i], ans);
}
cout << ans << "\n";
return 0;
}
dp의 원리를 조금 더 이해할 수 있는 문제였다고 생각한다.
'코딩테스트 > C++' 카테고리의 다른 글
| [백준 C++] 2225번: 합분해 (0) | 2024.04.27 |
|---|---|
| [백준 C++] 1699번: 제곱수의 합 (0) | 2024.04.25 |
| [백준 C++] 14002번: 가장 긴 증가하는 부분 수열 4 (0) | 2024.04.24 |
| [백준 C++] 11053번: 가장 긴 증가하는 부분 수열 (1) | 2024.04.22 |
| [백준 C++] 2193번: 이친수 (1) | 2024.04.21 |