ACM-ICPC 2018 沈阳赛区网络预赛 B Call of Accepted(表达式求值)
https://nanti.jisuanke.com/t/31443
题意
给出一个表达式,求最小值和最大值。
表达式中的运算符只有'+'、'-'、'*'、'd',xdy 表示一个 y 面的骰子 roll x 次的和,其中x>=0,y>=1,实际上它的最小值就是x,小于0时要强制变为0,最大值就是 x*y ,题目给的表达式保证运算都是合法的,并且中间过程和结果都是int范围内。
分析
表达式求值,多了一个d运算,维护最大最小值,在乘法的时候取所有极值的情况。
中序表达式->后序表达式(左->右):
数字:直接输出
运算符:将栈中所有优先级>=自己的运算符输出,之后入栈(栈为空就直接入栈)
(:入栈
):将之前所有运算符输出,直到遇到 '(' ,并且将 '('也输出
最后将栈中所有东西按顺序输出
后续表达式计算(左->右):
数字:入栈
运算符:取栈顶两个数字计算,结果入栈
遍历完后栈顶元素就是答案
#include<bits/stdc++.h> using namespace std; struct Node{ int type; int num; char op; }; map<char,int>mp; char str[110]; stack<char> s; queue<Node> que; void postfix(){//中缀转后缀 int len = strlen(str); for(int i=0;i<len;i++){ if(isdigit(str[i])){ int num=0; while(i<=len&&isdigit(str[i])){ num=num*10+str[i]-'0'; i++; } que.push(Node{0,num,'0'}); } if(i>=len) break; if(str[i]=='(') s.push(str[i]); else if(str[i]==')'){ while(s.top()!='('){ que.push(Node{1,0,s.top()}); s.pop(); } s.pop(); }else{ while(!s.empty()&&mp[s.top()]>=mp[str[i]]){ que.push(Node{1,0,s.top()}); s.pop(); } s.push(str[i]); } } while(!s.empty()){ que.push(Node{1,0,s.top()}); s.pop(); } } int main(){ mp['+']=mp['-']=1; mp['/']=mp['*']=2; mp['d']=3; while(~scanf("%s",str)){ postfix(); stack<int> small,big; while(!que.empty()){//后缀计算 Node u = que.front();que.pop(); if(u.type==0) small.push(u.num),big.push(u.num); else{ int sb = small.top(); small.pop(); int sa = small.top(); small.pop(); int bb = big.top(); big.pop(); int ba = big.top(); big.pop(); if (u.op == '+') sa += sb, ba += bb; else if (u.op == '-') sa -= bb, ba -= sb; else if (u.op == '*') { int minn = min(min(sa*sb, sa*bb), min(ba*sb, ba*bb)); int maxx = max(max(sa*sb, sa*bb), max(ba*sb, ba*bb)); sa = minn; ba = maxx; } else if (u.op == 'd') { if (sa < 0)sa = 0; ba *= bb; } small.push(sa); big.push(ba); } } printf("%d %d\n", small.top(), big.top()); } return 0; }