洛谷P1175

洛谷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';	
		}
	}	
}

相当考验代码能力,调了好长时间才过样例!
参考于 一位大佬的博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值