在openjudge上的一个题,想了想没思路去看了博客才知道。。
题目链接就不发了,谁知道以后还在不在。
题目大意如题。
解题思路:有很多前缀表达式转成后缀表达式来做的,我觉得很麻烦(懒),所以就找了直接求值的
开两个栈,分别保存符号和数字
遇到数字就直接压入数字栈(转换一下即可),遇到符号的情况:
1,‘(’ 直接压进去,等下一个右括号
2,‘)’, 说明这个时候应该运算了,运算的范围当然是这个右括号匹配的左括号为止
3,+-*/, 当然就是运算啦,不过要注意运算符优先级,如果当前的优先级比栈顶的大,那就先把这个压进去再说,如果比栈顶的小,自然就要先运算栈顶的再压当前的;
说说运算的细节:
运算的时候,取数字栈的前两个数字,pop出去,再运算出他们在符号栈栈顶操作下的结果,再压入数字栈,还要记得把当前操作符给pop出去
为什么要用栈?
栈的特性可以很好地保证按运算符的优先级来运算。
Code:
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define FAST ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
stack<int> num;
stack<char> ch;
void cal(){
int x = num.top(); num.pop();
int y = num.top(); num.pop();
switch(ch.top()){
case '+' : y += x; break;
case '-' : y -= x; break;
case '*' : y *= x; break;
case '/' : y /= x; break;
}
num.push(y);
ch.pop();
}
int lv(char c){
if(c == '+' || c == '-') return 1;
else if(c == '*' || c == '/') return 2;
else return 0;
}
bool check(char c){
if(c >= '0' && c <= '9') return true;
return false;
}
void init(){
while(!num.empty()) num.pop();
while(!ch.empty()) ch.pop();
}
int main()
{
FAST;
int t; cin >> t;
string s;
while(t--){
cin >> s;
init();
int len = s.size();
for(int i = 0; i < len;){
if(s[i] == '(') ch.push(s[i]), i++;
else if(s[i] == ')'){
while(ch.top() != '(') cal();
ch.pop();
i++;
}
else if(check(s[i])){
int x = 0;
while(check(s[i])) x = x * 10 + s[i++] - '0';
num.push(x);
}
else {
while(!ch.empty() && lv(s[i]) <= lv(ch.top())) cal();
ch.push(s[i]);
i++;
}
}
while(!ch.empty()) cal();
cout << num.top() << endl;
}
return 0;
}