알고리즘
백준 3015번: 오아시스 재결합 C++ 문제 해결
휘성티비
2024. 11. 24. 22:19

오늘은 백준에서 스택 문제 중 오아시스 재결합에 대해서 설명해보겠습니다.
먼저 이 문제는 복잡한 알고리즘을 필요로 하지는 않습니다.
제가 해결한 방법은 2493번: 탑 문제를 보고 오시면 쉽게 이해하실 수 있을 것 같습니다.
간단히 설명드리면
- 스택에 pair를 이용해 키와 키가 같은 사람의 수를 푸시
- 입력된 숫자와 앞에 선 사람의 키를 비교할 때 작은 숫자가 입력된 것이 아니면 기존 정보 삭제(작은 숫자가 입력되면 더 이전 숫자는 마주 볼 수 없음)
- 앞에 선 사람보다 키가 크거나 같으면 카운트 증가, 같을 경우에는 키가 같은 것을 나타내는 변수를 더해 스택에 푸시
좀 이해하기 어려울 수 있으니 코드를 분석 해보겠습니다.
#include <iostream>
#include <stack>
#define height first
#define equal second
using namespace std;
long long int n, num, result = 0;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
stack<pair<long long int, long long int>> S;
cin >> n;
while (n--) {
cin >> num;
long cnt = 0;
long equal_num = 0;
while (!S.empty()) {
if (num > S.top().height) {
cnt += S.top().equal + 1;
S.pop();
}
else if (num == S.top().height) {
cnt += S.top().equal + 1;
equal_num = S.top().equal + 1;
S.pop();
}
else {
break;
}
}
if (!S.empty()) cnt++;
S.push({ num, equal_num });
result += cnt;
}
cout << result;
return 0;
}
- cnt 변수와 equal_num 변수는 각각의 입력마다 마주보는 사람의 수, 중복되는 키를 가진 사람의 수를 저장합니다.
- 반복문 진행 중 num이 앞에 선 사람보다 크면 cnt를 추가하며 앞에 선 사람의 정보를 삭제합니다.
- 같을 경우에는 똑같이 cnt를 추가하며 정보를 삭제하지만 키가 겹치기에 equal_num의 수도 추가합니다.
- 작은 경우나 앞에 숫자가 없는 경우에는 앞에 선 사람 이전의 사람은 마주 볼 수 없어 패스합니다.
- if (!S.empty()) cnt++;은 작은 수가 입력되었을 때 반복문을 빠져나왔을 때 숫자가 남아있다면 그 숫자를 볼 수 있기에 cnt를 증가 연산합니다.
- 스택에 정보를 추가하고 result 변수에 쌍의 수를 더해줍니다.
- cnt 변수나 equal_num 변수에 수를 더할 때 스택의 top의 equal 요소에 1을 더하는지 궁금할 것입니다. 이는 우리가 앞서 계산할 때 여러 명의 키가 겹치면 이미 정보를 삭제해버려 몇 명이 겹치는지 몰라 1명만 계산하게 됩니다. 이를 위해 equal 요소를 만들어놨기에 더해서 변수에 입력합니다. 키가 안겹쳤다면 0인 상태기에 크게 신경 쓸 것은 없습니다.