题目链接:https://nanti.jisuanke.com/t/A1990
题目大意:
给你一个字符串其中包含+, -, *, '(', ')',数字(正整数),'d'(优先级最高)。xdy表示投掷x次y面的骰子。
现在问你这个表达式可能的最大值和最小值是多少?
思路:对一个xdy我们维护一个[L, R]最小值:x。最大值:x*y。把表达式求值的板子改一下就AC了。
#include<bits/stdc++.h> using namespace std; struct Interval { int L, R; Interval() {} Interval(int a, int b) : L(a), R(b) {} void Print() { printf("[%d,%d]\n", L, R); } }; Interval operator + (const Interval &a, const Interval &b) { return Interval(a.L + b.L, a.R + b.R); } Interval operator - (const Interval &a, const Interval &b) { return Interval(a.L - b.R, a.R - b.L); } Interval operator * (const Interval &a, const Interval &b) { int mn = min(min(a.L * b.L, a.L * b.R), min(a.R * b.L, a.R * b.R)); int mx = max(max(a.L * b.L, a.L * b.R), max(a.R * b.L, a.R * b.R)); return Interval(mn, mx); } Interval f(const Interval &a, const Interval &b) { assert(a.L >= 0 && b.L >= 1); return Interval(a.L, a.R * b.R); } char Precede(char a,char b) //得到a对b的优先级 { char op[8][8]= {// + - * / ( ) # d {'>','>','<','<','<','>','>','<'},// + {'>','>','<','<','<','>','>','<'},// - {'>','>','>','>','<','>','>','<'},// * {'>','>','>','>','<','>','>','<'},// / {'<','<','<','<','<','=','0','<'},// ( {'>','>','>','>','0','>','>','>'},// ) {'<','<','<','<','<','0','=','<'},// # {'>','>','>','>','<','>','>','>'} // d }; int x,y; switch(a) { case '+': x=0; break; case '-': x=1; break; case '*': x=2; break; case '/': x=3; break; case '(': x=4; break; case ')': x=5; break; case '#': x=6; break; case 'd': x=7; break; } switch(b) { case '+': y=0; break; case '-': y=1; break; case '*': y=2; break; case '/': y=3; break; case '(': y=4; break; case ')': y=5; break; case '#': y=6; break; case 'd': y=7; break; } return op[x][y]; } Interval Calculation(Interval num1,Interval num2,char op)//计算 { switch(op) { case '+': return num1+num2; case '-': return num1-num2; case '*': return num1*num2; case 'd': return f(num1, num2); } } int main() { string s; while(cin >> s) { if (s.find("+") == string::npos && s.find("-") == string::npos && s.find("*") == string::npos && s.find("/") == string::npos&& s.find("d") == string::npos) {//单独的一个数字 cout << s << " "<<s<<endl; continue; } s += '#';//表示结束 stack<Interval> opnd; stack<char> optr; optr.push('#'); int num = 0, i = 0; bool flag = false; while (s[i] != '#' || optr.top() != '#') { if (isdigit(s[i])) { flag = true; num = num * 10 + (s[i] - '0'); i++; continue; } else { if (flag) { opnd.push(Interval{num, num}); num = 0; flag = false; } switch(Precede(optr.top(),s[i])) { case '<': optr.push(s[i]); i++; break; case '=': optr.pop(); i++; break; case '>': char op = optr.top(); optr.pop(); Interval num1 = opnd.top(); opnd.pop(); Interval num2 = opnd.top(); opnd.pop(); Interval ans = Calculation(num2, num1, op); opnd.push(ans); break; } } } cout << opnd.top().L<<" "<< opnd.top().R<< endl; } return 0; } /* 1+2*(2+3)/5 */