洛谷P1175
题目传送门
相当恶心的一道题啊!!!
堪比今年儒略日!!!
思路:先中缀表达式转后缀,再对后缀表达式求值。
中缀表达式转后缀:O(n)扫一遍输入的中缀表达式:
1.遇到数:直接输出
2.遇到左括号:左括号直接入栈。
3.遇到运算符号:利用建立的符号栈,栈内总原则为高级运算压在低级运算之上。
4.遇到加、减、乘、除、乘方,按照正常的运算优先级处理(可以看一下P1981 表达式求值)。从栈顶开始,将运算优先级高于或等于待入栈符号的所有符号逐一出栈输出,直到遇到栈内优先级低于入栈符号的符号or左括号为止。
5.遇到右括号:持续进行出栈操作,输出运算符,直至遇到左括号。
扫完后,将符号栈内所有剩余符号出栈输出。这时输出的字符串便为输入的中缀表达式的后缀表达式。然后将后缀表达式直接进行运算即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
char ch[maxn],ss[maxn],last[maxn];//charac:中缀转后缀时用的运算符栈,ss:存储中缀表达式,last:存储后缀表达式
int totc,first[maxn],len,ans[maxn],totl,cnt;//first:运算符优先级,ans:求后缀表达式时存储数字
int main()
{
scanf("%s",ss+1);
len=strlen(ss+1);
first[40]=first[41]=first[94]=2;//制定优先级(first值大的运算优先级高)数字分别对应运算符的Ascall码
first[42]=first[47]=1;
for(int i=1;i<=len;i++)
{
if('0'<=ss[i]&&ss[i]<='9')
{
last[++cnt]=ss[i]; //遇到数:直接输出
}
if(ss[i]=='(')
{
ch[++totc]=ss[i];//遇到左括号:左括号直接入栈。
}
if(ss[i]=='+'||ss[i]=='-'||ss[i]=='*'||ss[i]=='/'||ss[i]=='^')
{
//遇到加、减、乘、除、乘方,按照正常的运算优先级处理。
//从栈顶开始,将运算优先级高于或等于待入栈符号的所有符号逐一出栈输出,
//直到遇到栈内优先级低于入栈符号的符号 or 左括号为止。
//然后将当前运算符压入栈中
while(totc>0&&first[(int)ch[totc]]>=first[(int)ss[i]])
{
if(ch[totc]=='(')
{
break;
}
last[++cnt]=ch[totc];
totc--;
}
ch[++totc]=ss[i];
}
if(ss[i]==')')
{
//遇到右括号:持续进行出栈操作,输出运算符,直至遇到左括号。
while(ch[totc]!='(')
{
last[++cnt]=(int)ch[totc];
totc--;
}
totc--; //左括号只出栈不输出
}
}
for(int i=totc;i>=1;i--)
{
last[++cnt]=ch[i];
}
for(int i=1;i<=cnt;i++)
{
cout<<last[i]<<" ";
}
cout<<'\n';
for(int i=1;i<=cnt;i++) //对后缀表达式求值
{
if('0'<=last[i]&&last[i]<='9')
{
ans[++totl]=last[i]-'0';
}
if(last[i]<'0'||last[i]>'9')
{
if(last[i]=='+')
{
ans[totl-1]+=ans[totl];
}
if(last[i]=='-')
{
ans[totl-1]-=ans[totl];
}
if(last[i]=='*')
{
ans[totl-1]*=ans[totl];
}
if(last[i]=='/')
{
ans[totl-1]/=ans[totl];
}
if(last[i]=='^')
{
int temp=ans[totl-1];
for(int j=1;j<=ans[totl]-1;j++)
{
ans[totl-1]*=temp;
}
}
totl--;
for(int j=1;j<=totl;j++)
{
cout<<ans[j]<<" ";
}
for(int j=i+1;j<=cnt;j++)
{
cout<<last[j]<<" ";
}
cout<<'\n';
}
}
}
相当考验代码能力,调了好长时间才过样例!
参考于 一位大佬的博客