https://www.acmicpc.net/problem/11501
11501번: 주식
입력의 첫 줄에는 테스트케이스 수를 나타내는 자연수 T가 주어진다. 각 테스트케이스 별로 첫 줄에는 날의 수를 나타내는 자연수 N(2 ≤ N ≤ 1,000,000)이 주어지고, 둘째 줄에는 날 별 주가를 나타
www.acmicpc.net
그리디를 오늘부터 제대로 시작해보려고 한다.
먼저 이 문제를 고르게되었다.
그리디 알고리즘이 '현재에서 가장 Best인 항목을 선택' 하기에 이번에도 이를 적용하려고 하였다.
첫번째 시도
고수익을 얻기 위해선 무조건 최고점일 때 판매를 해야한다.
최고점을 구하는 함수를 만들어 이를 사용하였다.
테스트 케이스 중 1 1 3 1 2 의 경우, MAX가 3이기 때문에 고점을 고정하여 진행하게 되면 3 다음 1, 2에서 아무런 작업도 수행하지 않기에 4라는 결과가 나온다. (정답 5)
따라서, MAX에서 판매 후 고점을 새로 구하는 함수를 이용한 것이다.
이 방법을 이용하면, 테스트케이스 Loop 까지 포함하여 총 O(N^3)의 시간이 걸리기에 시간 초과가 나온다.
두번째 시도
고점을 매번 구하지 않고 진행하는 방법을 생각해보았다. 역순으로 진행 시 고점 선정과 판매가 유리하여 이를 이용하자.
1 1 3 1 2를 이용해보자.
1) 2
마지막 날은 무조건 판매해야 하기에 MAX를 2로 두자.
2) 1
MAX보다 작은 값이므로 판매하는 행동을 한다.
이때 수익은 MAX - Current 이다.
3) 3
MAX보다 큰 값이 왔기 때문에, 이전의 MAX(정방향으로 보았을 때)값이므로 업데이트한다.
4) 1
MAX보다 작은 값이기에 판매한다.
5) 1
MAX보다 작은 값이므로 판매한다.
따라서, 알고리즘을 요약하면 다음과 같다.
1. MAX < Current
- 이전의 MAX이므로 MAX = Current
2. 나머지 경우
- MAX에서 판매하는 주이므로, sum += MAX - Current
코드
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
int arr[1000001];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t, n;
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
int large = -1;
long long sum = 0;
for (int cur = n; cur >= 1; cur--) {
if (large < arr[cur]) {
//cout << "changed: " << large << endl;
large = max(large, arr[cur]);
}
else if (large >= arr[cur]) {
int tmp = large - arr[cur];
sum += tmp;
}
}
cout << sum << "\n";
}
}
[ 참고 ]
'📊알고리즘 > BOJ' 카테고리의 다른 글
[그리디 #3] 카드 합체 놀이 (0) | 2024.02.05 |
---|---|
[그리디 #2] BOJ1541 잃어버린 괄호 (0) | 2023.11.12 |
{BOJ 2839} 설탕 배달 (DP) (0) | 2023.09.24 |
[DP #24] (BOJ 2225) 합분해 (0) | 2023.09.07 |
[DP #22] (BOJ 15990) 1,2,3 더하기 5 (0) | 2023.09.02 |