일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- c++
- 정렬
- 딥러닝
- Game Data Analysis
- p-value
- 알고리즘
- anomaly detection
- 구현
- ML
- 백준
- 자료구조
- 스택
- 큐
- 통계
- Queue
- DP
- BFS
- Anti Cheat
- datascience
- 중앙갑
- Machine learning
- Stack
- Deeplearning
- AA test
- Journal Review
- cs231n
- classification
- Python
- 7569번
- 그리디
- Today
- Total
Software Hyena::
[백준 2841번] - 외계인의 기타 연주 / C++ 본문
www.acmicpc.net/problem/2841
2841번: 외계인의 기타 연주
첫째 줄에 멜로디에 포함되어 있는 음의 수 N과 한 줄에 있는 프렛의 수 P가 주어진다. (N ≤ 500,000, 2 ≤ P ≤ 300,000) 다음 N개 줄에는 멜로디의 한 음을 나타내는 두 정수가 주어진다. 첫 번째 정수
www.acmicpc.net
문제
상근이의 상상의 친구 외계인은 손가락을 수십억개 가지고 있다. 어느 날 외계인은 기타가 치고 싶었고, 인터넷에서 간단한 멜로디를 검색했다. 이제 이 기타를 치려고 한다.
보통 기타는 1번 줄부터 6번 줄까지 총 6개의 줄이 있고, 각 줄은 P개의 프렛으로 나누어져 있다. 프렛의 번호도 1번부터 P번까지 나누어져 있다.
멜로디는 음의 연속이고, 각 음은 줄에서 해당하는 프렛을 누르고 줄을 튕기면 연주할 수 있다. 예를 들면, 4번 줄의 8번 프렛을 누르고 튕길 수 있다. 만약, 어떤 줄의 프렛을 여러 개 누르고 있다면, 가장 높은 프렛의 음이 발생한다.
예를 들어, 3번 줄의 5번 프렛을 이미 누르고 있다고 하자. 이때, 7번 프렛을 누른 음을 연주하려면, 5번 프렛을 누르는 손을 떼지 않고 다른 손가락으로 7번 프렛을 누르고 줄을 튕기면 된다. 여기서 2번 프렛의 음을 연주하려고 한다면, 5번과 7번을 누르던 손가락을 뗀 다음에 2번 프렛을 누르고 연주해야 한다.
이렇게 손가락으로 프렛을 한 번 누르거나 떼는 것을 손가락을 한 번 움직였다고 한다. 어떤 멜로디가 주어졌을 때, 손가락의 가장 적게 움직이는 회수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 멜로디에 포함되어 있는 음의 수 N과 한 줄에 있는 프렛의 수 P가 주어진다. (N ≤ 500,000, 2 ≤ P ≤ 300,000)
다음 N개 줄에는 멜로디의 한 음을 나타내는 두 정수가 주어진다. 첫 번째 정수는 줄의 번호이고 두 번째 정수는 그 줄에서 눌러야 하는 프렛의 번호이다. 입력으로 주어진 음의 순서대로 기타를 연주해야 한다.
출력
첫째 줄에 멜로디를 연주하는데 필요한 최소 손가락 움직임을 출력한다.
--------------------------------------------------------------------------------------------------------
풀이
<C++>
#include <iostream>
#include <stack>
using namespace std;
int line[500001];
int flat[500001];
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N, P;
cin >> N >> P;
for (int i = 0; i < N; ++i) {
cin >> line[i] >> flat[i];
}
stack<int> guitar[7];
int num = 0;
for (int i = 0; i < N; ++i) {
while (true) {
if (guitar[line[i] - 1].empty()) {
guitar[line[i] - 1].push(flat[i]);
++num;
break;
}
else if (guitar[line[i] - 1].top() < flat[i]) {
guitar[line[i] - 1].push(flat[i]);
++num;
break;
}
else if (guitar[line[i] - 1].top() == flat[i]) {
break;
}
else if (guitar[line[i] - 1].top() > flat[i]) {
guitar[line[i] - 1].pop();
++num;
}
}
}
cout << num;
return 0;
}
손가락이 무한대라서 스택을 이용해서 풀면 간단한 알고리즘으로 풀리는 문제이다.
1. N과, P를 입력받는다. (P는 입력받고 사용하지 않았다)
2. N개의 음들을 입력받아, 줄의 번호, 플랫의 번호를 각각 다른 배열에 저장한다.
3. guitar라는 int형 stack에 기타줄의 번호마다 반복문을 통해 아래의 알고리즘에 따라 연산을 수행한다.
- guitar[줄번호] 가 비어있으면, flat[i]를 입력한다.
- guitar[줄번호]의 top이 flat[i] 보다 작으면, flat[i]를 스택에 넣고, num을 더해준다.
- guitar[줄번호]의 top이 flat[i] 와 같으면 break 한다.
- guitar[줄번호]의 top이 flat[i] 보다 크면, 스택에서 pop을 해주고, num을 더해준다.
4. num을 출력한다.
'알고리즘 > 백준' 카테고리의 다른 글
[백준 1874번] - 스택 수열 / C++ (0) | 2021.03.13 |
---|---|
[백준 2504번] - 괄호의 값 / C++ (0) | 2021.03.10 |
[백준 3986번] - 좋은 단어 / C++ (stack) (0) | 2021.03.05 |
[백준 11916번] -볼질 / C++ (Class로 구현해보기) (0) | 2021.02.26 |
[백준 11292번] - 키 큰 사람 / C++ (0) | 2021.02.25 |