河南省acm第九届省赛--《表达式求值》--栈和后缀表达式的变形--手速题
表达式求值
- 描述
- 假设表达式定义为:1. 一个十进制的正整数 X 是一个表达式。2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+.3. 如果 X 和 Y 是 表达式,则 函数 Smax(X,Y)也是表达式,其值为:先分别求出 X ,Y值的各位数字之和,再从中选最大数。4.如果 X 是 表达式,则 (X)也是表达式。 例如:表达式 12*(2+3)+Smax(333,220+280) 的值为 69。 请你编程,对给定的表达式,输出其值。
- 输入
- 【标准输入】 第一行: T 表示要计算的表达式个数 (1≤ T ≤ 10) 接下来有 T 行, 每行是一个字符串,表示待求的表达式,长度<=1000
- 输出
- 【标准输出】 对于每个表达式,输出一行,表示对应表达式的值。
- 样例输入
-
3
12+2*3
12*(2+3)
12*(2+3)+Smax(333,220+280) - 样例输出
-
18
60
69 - 来源
- 河南省第九届省赛
-
大致思路:
- 用stack来实现的后缀表达式的解法。
- 每次需要考虑运算符的优先级,怎么考虑?
- 分类讨论:
- 1、顺序遍历表达式,当前符号位为加号时,判断上一位,是加号(同级),取num栈两个栈顶元素和op栈栈顶符号进行一次运算,再放回num栈中。
- 2、当前符号位为乘号,如果乘号的前后都是数字——那么一定可以进行乘法运算一次;由于在顺序遍历数组时,不方便预知后面一位是否为数字,可以在每次读入一位数字后进行判断;乘号的前后都是数字时,可以放心做乘。
- 3、当前符号位为S,Smax可以特殊处理,不存入“Smax”,只保留中间的', ' 即可!把', ' 号当做特殊运算符(类似与‘*’和‘+’)。
- 4、遇见左括号,存入;遇见右括号,开始进行计算一直计算到左括号,并把左括号删除。还有就是第三步', '的左右,进行运算时——要确保‘,’左右两边都是一个确定的数值!不然没法运算,所以对‘,’左边必须进行处理成一个整数!
- 5、加强版的样例 :
-
21
1+2
1+2+3
12*3+4*1*2
12*(1+3*4+1)12*(2+3*1)+Smax(333,220*1+280)
12*(2+3)+(1+1*333,220*1+280)题解:(有稍微的注释)
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<stdlib.h>
#include<map>
#include<stack>
#include<queue>
#define inf 0x3f3f3f3f//19:04--
#define N 1008
#define ll long long
using namespace std;
stack<int>num;
stack<char>op;
char str[N];
void cal(char opx){//依据opx来计算num栈上的前两位
if(num.size()<=)return ;
int n1,n2;
n1=num.top();num.pop();
n2=num.top();num.pop();
if(opx=='*')
num.push(n1*n2);
else if(opx=='+')
num.push(n1+n2);
else if(opx==','){
int s1=,s2=;
while(n1>){
s1+=n1%;n1/=;
}
while(n2>){
s2+=n2%;n2/=;
}
num.push(max(s1,s2));
}
}
void cal2(char opx){//计算到左括号为止(Smax可以特殊处理:只保留中间的','即可!把','号当做特殊运算符)
if(opx==','){
while(op.top()!='('){
cal(op.top());
op.pop();
}
// op.pop(); }else{
while(op.top()!='('){
cal(op.top());
op.pop();
}
op.pop();//去掉左括号
}
}
int get_nextnum(int i){//分离出从str[]数组下标i开始的数字,注意要返回j
int j,sum=str[i]-'';
for(j=i+;j<strlen(str);j++){
if(str[j]>=''&&str[j]<='')
sum=sum*+str[j]-'';
else
break;
}
num.push(sum);
return j;
} void solve(){
int ans=;
int len=strlen(str);
for(int i=;i<len;){
if(str[i]==' ')
i++;
else if(str[i]>=''&&str[i]<=''){
i=get_nextnum(i);//获取该位置数字
if(!op.empty()&&op.top()=='*'){//当读入一个数字后,发现上一位是乘号:及时做乘
cal('*');
op.pop();
}
}
else if(str[i]=='*'){
op.push('*');
i++;
}
else if(str[i]=='+'){
if(!op.empty()&&op.top()=='+'){
cal(str[i]);//可以省略一push一次‘+’,毕竟先pop‘+’后push‘+’
}
else if(!op.empty()&&op.top()=='*'){
cal('*');
op.pop();
op.push('+');
}
else
op.push('+');
i++;
}
else if(str[i]=='S'){
i+=;
}
else if(str[i]==','){
cal2(',');//计算到左括号!
op.push(str[i++]);
}
else if(str[i]=='('){
op.push(str[i++]);
}
else if(str[i]==')'){
cal2(')');
i++;
}
} while(op.size()>=){
cal(op.top());
op.pop();
} ans=num.top(); printf("%d\n",ans);
} int main(){
int T;
scanf("%d\n",&T); while(T--){
while(num.size()>)num.pop();//清空整个num栈和op栈
while(op.size()>)op.pop();
gets(str);
solve();
} return ;
}
河南省acm第九届省赛--《表达式求值》--栈和后缀表达式的变形--手速题的更多相关文章
- 第四届河南省ACM 表达式求值 栈
表达式求值 时间限制: 1 Sec 内存限制: 128 MB 提交: 14 解决: 7 [提交][状态][讨论版] 题目描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简 ...
- 表达式求值(noip2015等价表达式)
题目大意 给一个含字母a的表达式,求n个选项中表达式跟一开始那个等价的有哪些 做法 模拟一个多项式显然难以实现那么我们高兴的找一些素数代入表达式,再随便找一个素数做模表达式求值优先级表 - ( ) + ...
- 表达式求值 (栈) 用C++实现
#include <cstdio> #include <cstdlib> #include <cmath> #include <stack> #incl ...
- Python解析 算数表达式求值 栈的使用
使用Python实现一种算数表达式求值的算法,模拟这种使用栈的方式,这是由E.W.Dijkstra在20世纪60年代发明的一种非常简单的算法.代码模拟仅仅表现一种编程思想,代码的逻辑并不完全: if ...
- 2015 UESTC 数据结构专题N题 秋实大哥搞算数 表达式求值/栈
秋实大哥搞算数 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1074 Des ...
- 【zzuli-1923】表达式求值
题目描述 假设表达式定义为:1. 一个十进制的正整数 X 是一个表达式.2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+.3. 如果 X 和 Y 是 表达式,则 ...
- C语言中缀表达式求值(综合)
题前需要了解的:中缀.后缀表达式是什么?(不知道你们知不知道,反正我当时不知道,搜的百度) 基本思路:先把输入的中缀表达式→后缀表达式→进行计算得出结果 栈:"先进先出,先进后出" ...
- NYOJ 1272 表达式求值 第九届省赛 (字符串处理)
title: 表达式求值 第九届省赛 nyoj 1272 tags: [栈,数据结构] 题目链接 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表 ...
- java实现算术表达式求值
需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后 ...
随机推荐
- 反馈神经网络Hopfield网络
一.前言 经过一段时间的积累,对于神经网络,已经基本掌握了感知器.BP算法及其改进.AdaLine等最为简单和基础的前馈型神经网络知识,下面开启的是基于反馈型的神经网络Hopfiled神经网络.前馈型 ...
- centos7 install docker
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo y ...
- ATT&CK框架学习
ATT&CK模型 ATT&CK是分析攻击者行为(即TTPs)的威胁分析框架.ATT&CK框架核心就是以矩阵形式展现的TTPs,即Tactics, Techniques and ...
- Java多态的6大特性|乐字节
大家好,我是乐字节的小乐,前几天讲完了Java继承,接下来我们会讲述Java多态. 以上就是本次学习的6大任务.我们依次来看. 一. Object类 Object类是所有Java类的根基类. 如果在类 ...
- 谈谈redis的热key问题如何解决
引言 讲了几天的数据库系列的文章,大家一定看烦了,其实还没讲完...(以下省略一万字).今天我们换换口味,来写redis方面的内容,谈谈热key问题如何解决.其实热key问题说来也很简单,就是瞬间有几 ...
- [WinForm] - "更新 DataSet 应用程序集对象失败,Visual Studio 自动重启" 之解决
背景 在 WinForm 解决方案中,更新 DataSet 应用程序集对象失败,Visual Studio 自动重启. 试一试 1. 更新 .xsd 时打开对应的 .Designer.cs.2. 如果 ...
- Session中清除对象方法比较
转载. https://blog.csdn.net/u014401141/article/details/51816308 Session中清除对象方法比较 http://blog.csdn.ne ...
- u盘传输文件时提示过大
(无需格式化U盘) 1.拷贝大文件时提示目标文件系统过大,无法复制 2.查U盘,发现剩余空间足够: 3.分析原因,是由于U盘的格式问题导致的,当期的磁盘格式是FAT32类型的,无拷贝过大的文件: 4. ...
- Git--远程仓库版本回退方法
Git--远程仓库版本回退方法 1 简介 最近在使用git时遇到了远程分支需要版本回滚的情况,于是做了一下研究,写下这篇博客. 2 问题 如果提交了一个错误的版本,怎么回退版本? 如果提交了一个错误的 ...
- python学习-60 面向对象设计
面向对象设计 1.三大编程范式 --面向过程编程 --函数式编程 --面向对象编程 2.编程进化论 --编程最开始就是无组织无结构,从简单控制流中按步写指令 --从上述的指令中提取重复的代码快或逻辑, ...