티스토리 뷰
#include <bits/stdc++.h>
using namespace std;
deque<long long> num;
deque<char> oper;
char level(char & op) { //연산자 우선순위
char ret = 2; //곱하기 나누기
if(op == '+' || op == '-') ret = 1; //더하기 빼기
return ret;
}
long long left(char & op) { //처음 그리고 두번째 숫자의 계산
long long ret = 0;
if(op == '+') ret = num.front() + (*(num.begin()+1));
else if(op == '-') ret = num.front() - (*(num.begin()+1));
else if(op == '*') ret = num.front() * (*(num.begin()+1));
else if(op == '/') ret = num.front() / (*(num.begin()+1));
return ret;
}
long long right(char & op) { //마지막-1 숫자와 마지막 숫자의 계산
long long ret = 0;
if(op == '+') ret = (*(num.end()-2)) + num.back();
else if(op == '-') ret = (*(num.end()-2)) - num.back();
else if(op == '*') ret = (*(num.end()-2)) * num.back();
else if(op == '/') ret = (*(num.end()-2)) / num.back();
return ret;
}
void removeL(long long & tmp) { //왼쪽을 제거하는 경우
//수를 담은 덱에선 2개를 꺼낸 다음
num.pop_front();
num.pop_front();
oper.pop_front(); //계산에 이용된 연산자도 제거
//빼낸 두 수를 계산한 값을 넣어줍니다.
num.emplace_front(tmp);
}
void removeR(long long & tmp2) { //오른쪽을 제거하는 경우
//수를 담은 덱에선 2개를 꺼낸 다음
num.pop_back();
num.pop_back();
oper.pop_back(); //계산에 이용된 연산자도 제거
//빼낸 두 수를 계산한 값을 넣어줍니다.
num.emplace_back(tmp2);
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0);
string buf; //문자열
cin >> buf;
long long tmp=0, tmp2=0;
int i=0;
bool isMinus = false; //처음 문자가 -이면 true로 바뀝니다.
////////////////////////////////////////////////////////////////////////////
//파싱
if(buf[0] == '-') { //처음 문자가 - 인가?
isMinus = true;
i = 1; // - 다음부터 수와 연산자를 분리한다.
}
for(;buf[i]!=0;i++) { //수와 연산자 분리
if(buf[i] >= 48) { //숫자가 나오면 tmp에 10을 곱한다음 이번 문자를 수로 변환해서 더해준다.
tmp *= 10;
tmp += buf[i]-48;
}
else { //연산자가 나오면 그동한 구했던 수(tmp)을 덱에 넣고 0으로 초기화 해준다. 또한 연산자도 따로 덱에 넣어준다.
num.emplace_back(tmp);
tmp = 0;
oper.emplace_back(buf[i]);
}
}
//마지막으로 구해진 수를 덱에 넣어준다.
num.emplace_back(tmp);
tmp = 0;
if(isMinus) num.front() *= -1; //처음이 - 이었다면
//////////////////////////////////////////////////////////////////
//왼쪽과, 오른쪽을 봅니다.
//연산자 우선순위가 높은 쪽을 계산후, 두 수를 덱에 뺀 다음 계산값을 덱에 넣어줍니다.
//만약 같다면 계산결과가 더 큰 쪽의 두 수를 덱에 뺀 다음 계산값을 덱에 넣어줍니다.
//또한 계산결과도 같다면 왼쪽의 두스를 덱에 뺀 다음 그 둘의 계산값을 덱에 넣어줍니다.
char op1, op2;
while(!oper.empty()) { //연산자가 남아 있는게 없다면 반복문을 종료합니다.
op1 = level(oper.front()); //왼쪽 연산자의 우선순위
op2 = level(oper.back()); //오른쪽 연산자의 우선순위
tmp = left(oper.front()); //왼쪽 계산값
tmp2 = right(oper.back()); //오른쪽 계산값
if(op1 > op2) removeL(tmp); //왼쪽의 우선순위가 더 높은 경우
else if(op1 < op2) removeR(tmp2); //오른쪽의 우선순위가 더 높은 경우
else { //우선순위가 서로 같은 경우
if(tmp >= tmp2) { //계산값이 왼쪽이 같거나 더 큰 경우
removeL(tmp);
} else { //계산값이 오른쪽이 더 큰 경우
removeR(tmp2);
}
}
}
cout << num.front(); //덱에 하나남은 최종값을 출력
}
풀이 : 문자열, 덱
1. 수를 담을 덱과 (long long) 연산자를 담을 덱(char)을 준비합니다.
2. 문자열을 입력받으면, 여기서 수와 문자열을 분리해줍니다. 이때 가장 앞에 - 가 나오는 경우, -을 제외 한 다음, 숫자와 연산자들을 덱에 넣은 다음, 다 끝나고 나서, 수를 담은 덱의 가장 처음 노드의 값에 -1을 곱해줍니다.
3. 왼쪽, 오른쪽의 연산자들의 우선순위를 구하고, 왼쪽 오른쪽의 계산값을 구해놓습니다. 그런다음 우선순위가 높은곳을 먼저 해결(덱에서 두개를 뺀 다음, 이들의 계산값을 다시 덱에 넣음, 계산에 사용된 연산자도 덱에서 제거) 합니다. 만약 우선순위가 같다면, 왼쪽의 계산결과가 같거나 더 크다면, 왼쪽을 해결 아니라면 오른쪽을 해결합니다. 이를 덱에 있는 연산자가 남아있지 않을 때 까지 반복합니다.
4. 마지막 남은 수를 출력합니다.
https://www.acmicpc.net/problem/19591
19591번: 독특한 계산기
숫자, '+', '*', '-', '/'로만 이루어진 길이가 106 이하인 수식이 주어진다. 계산 과정 중의 모든 수는 −263 이상 263 미만이며, 0으로 나누는 경우는 없다. 숫자 앞에 불필요한 0이 있을 수 있다.
www.acmicpc.net
'c++ > BAEKJOON' 카테고리의 다른 글
c++ 14496번 그대, 그머가 되어(백준) (0) | 2023.09.22 |
---|---|
c++ 11725 트리의 부모 찾기 (백준) (0) | 2023.09.17 |
c++ 28078번 중력 큐 (백준) (0) | 2023.09.06 |
c++ 14897번 서로 다른 수와 쿼리 1 (백준) (0) | 2023.07.14 |
c++ 26086번 어려운 스케줄링 (백준) (0) | 2023.07.09 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- BFS
- 정렬
- 누적 합
- 그리디
- Krustal
- C++
- Lazy Propagation
- 스택
- 기하학
- 최대공약수
- 오프라인 쿼리
- C언어
- DP
- DFS
- 누적합
- Segment Tree
- 1835번
- 최소 스패닝 트리
- 덱
- 세그먼트 트리
- PASCAL
- union
- 1835
- java
- 백준
- 브루트포스
- 플로이드
- 그래프
- find
- XOR
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함