题目传送门
题意:
- 给你一个表达式由+,-,*,d,( ),组成。运算符左边的元素>=0,右边的元素>=1
- 其中d的运算规则是,比如3d6,指3次掷6面体骰子,出现的数值为[1,6]。
- 现在让你求表达式的最大和最小
做法:
- 经典的中缀表达式转后缀表达式(逆波兰式)
- 算法:复习复习~
- 中缀表达式 —> 后缀表达式
- 1. 数字:直接输出
- 2. 运算符:如果栈顶运算符的优先级>=当前,将栈顶运算符输出,出栈。再将当前运算符入栈。栈为空时,直接入栈。
- 3.遇到 ‘(’ 直接入栈。
- 4.遇到’)’ ,将栈中所有的运算符输出并出栈,直到遇到’(’,并且‘(’也输出并出栈。
- 后缀表达式计算:
- 1.当前为数字:入栈
- 2.当前为操作符: 取栈顶两个元素进行计算,结果入栈
- 3.当遍历完后,栈顶元素为表达式运算结果。
- 本题目的话注意维护一下最大最小值以及d的优先级大于乘法即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define IO ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x) push_back(x)
#define sz(x) (int)(x).size()
#define sc(x) scanf("%d",&x)
#define abs(x) ((x)<0 ? -(x) : x)
#define all(x) x.begin(),x.end()
#define mk(x,y) make_pair(x,y)
#define fin freopen("in.txt","r",stdin)
#define fout freopen("out.txt","w",stdout)
typedef long long ll;
typedef pair<int,int> P;
const int mod = 1e9+7;
const int maxm = 1e8+5;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 1ll<<62;
char str[maxn],pp[maxn];
inline int check(char c)
{
switch (c)
{
case '(':
return 0;
case '+':
case '-':
return 10;
case '*':
return 20;
case 'd':
return 21;
case ')':
return 100;
}
}
void trans(char *str)//将中缀表达式转换后缀表达式
{
stack<char>ss;
int i = 0,j = 0;
while(str[i]!='#')
{
if(str[i]=='(')
{
ss.push(str[i]);
}
else if(str[i]==')')
{
while(ss.top()!='(')
{
pp[j++]=ss.top();
ss.pop();
}
ss.pop();
}
else if(str[i]=='+'||str[i]=='-')
{
while(!ss.empty()&&check(str[i])<=check(ss.top()))
{
pp[j++]=ss.top();
ss.pop();
}
ss.push(str[i]);
}
else if(str[i]=='*'||str[i]=='d')
{
while((!ss.empty()&&check(str[i])<=check(ss.top()))||(!ss.empty()&&check(str[i])<=check(ss.top())))
{
pp[j++]=ss.top();
ss.pop();
}
ss.push(str[i]);
}
else
{
while(str[i]>='0'&&str[i]<='9')
{
pp[j++]=str[i];
i++;
}
i--;
pp[j++]='#';
}
i++;
}
while(!ss.empty())
{
pp[j++]=ss.top();
ss.pop();
}
pp[j]='#';
for(int i=0;i<j;i++) cout<<pp[i];
cout<<endl;
}
stack<int> mn;
stack<int> mx;
void cal(char c)
{
int sb = mn.top(); mn.pop();
int sa = mn.top(); mn.pop();
int bb = mx.top(); mx.pop();
int ba = mx.top(); mx.pop();
if(c == '+')
sa+=sb,ba+=bb;
else if(c == '-')
sa-=bb,ba-=sb;
else if(c == '*')
{
int minn = min(min(sa*sb,sa*bb),min(ba*bb,ba*sb));
int maxx = max(max(sa*sb,sa*bb),max(ba*bb,ba*sb));
sa = minn;
ba = maxx;
}
else if(c == 'd')
{
if(sa<0) sa = 0;
ba *= bb;
}
mn.push(sa);
mx.push(ba);
}
void compvalue()//计算后缀表达式的值
{
int i = 0;
while(pp[i]!='#')
{
if(pp[i] == '+' || pp[i] == '-' || pp[i] == '*' || pp[i] == 'd') cal(pp[i]);
else
{
int d=0;
while(pp[i]>='0'&&pp[i]<='9')
{
d=10*d+pp[i]-'0';
i++;
}
mn.push(d);
mx.push(d);
}
i++;
}
printf("%d %d\n",mn.top(),mx.top());
}
void solve() //计算中缀表达式的值
{
while(!mx.empty()) mx.pop();
while(!mn.empty()) mn.pop();
int n=strlen(str);
str[n]='#';
str[n+1]='\0';
trans(str);
compvalue();
}
int main()
{
// fin;
IO;
while(cin>>str)
{
solve();
}
return 0;
}