数据结构——POJ 1686 Lazy Math Instructor 栈的应用
Description
You are to write a program to read different formulas and determine whether or not they are arithmetically equivalent.
Input
that is the number of test cases. Following the first line, there are
two lines for each test case. A test case consists of two arithmetic
expressions, each on a separate line with at most 80 characters. There
is no blank line in the input. An expression contains one or more of the
following:
- Single letter variables (case insensitive).
- Single digit numbers.
- Matched left and right parentheses.
- Binary operators +, - and * which are used for addition, subtraction and multiplication respectively.
- Arbitrary number of blank or tab characters between above tokens.
Note:
Expressions are syntactically correct and evaluated from left to right
with equal precedence (priority) for all operators. The coefficients and
exponents of the variables are guaranteed to fit in 16-bit integers.
Output
expressions for each test data are arithmetically equivalent, "YES",
otherwise "NO" must be printed as the output of the program. Output
should be all in upper-case characters.
Sample Input
3
(a+b-c)*2
(a+a)+(b*2)-(3*c)+c
a*2-(a+c)+((a+c+e)*2)
3*a+c+(2*e)
(a-b)*(a-b)
(a*a)-(2*a*b)-(b*b)
Sample Output
YES
YES
NO
解题思路:我的程序是把每个 'a'--'z' 的字母分别hash成0--25 再把每个 'A'--'Z' 的字母分别hash成0--25
给出两个数学式子判断其结果是否相等。
解法:
1,用栈将表达式转换成为后缀式,然后计算后缀表达式的只判断其是否相等。
2,其中有一个问题就是字母转换之后如何算其值来代表其字母的值,我用的是(int)s1[i]直接将其ASCII作为数值对待,结果也AC了(看来这个
题只是判断两个表达式是否在数值上是等价的而不是判断两个公式是否等价 比如说:(b-a+c)*2 与
(1+c)*2也相等,但是如果作为公式的话这两个是不相等的)。
规则
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要用到栈,具体过程如下:
1)如果遇到操作数,我们就直接将其输出。
2)如果遇到左括号,我们直接将其放入到栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“-“)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。优先级从大到小顺序为:" * " 与 " / "," + " 与 " - ","(",也就是说"
( "优先级最低。
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
规则
规则很多,还是用实例比较容易说清楚整个过程。以上面的转换为例,输入为a + b * c + (d * e + f)*g,处理过程如下:
1)首先读到a,直接输出。
2)读到“+”,将其放入到栈中。
3)读到b,直接输出。
此时栈和输出的情况如下:
4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。
5)读到c,直接输出。
此时栈和输出情况如下:
6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级与读到的操作符" + "一样,所以也要弹出并输出。然后再将读到的" + "压入栈中。
此时栈和输出情况如下:
7)下一个读到的为"(",所以直接放入到栈中。
8)读到d,将其直接输出。
此时栈和输出情况如下:
9)读到" * ",由于只有”(“的优先级最低,遇到" ) "的时候左括号"("才会弹出,所以" * "压入栈中。
10)读到e,直接输出。
此时栈和输出情况如下:
11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。
12)读到f,直接输出。
此时栈和输出情况:
13)接下来读到“)”,则直接将栈中元素弹出并输出直到遇到"("为止。这里右括号前只有一个操作符"+"被弹出并输出。
14)读到" * ",压入栈中。读到g,直接输出。
15)此时输入数据已经读到末尾,栈中还有两个操作符“*”和" + ",直接弹出并输出。
至此整个转换过程完成。程序实现代码后续再补充了。
然后是后缀表达式求值
后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。假定待求值的后缀表达式为:6 5 2 3 + 8 * + 3 + *,则其求值过程如下:
1)遍历表达式,遇到的数字首先放入栈中,此时栈如下所示:
2)接着读到“+”,则弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中。
3)读到8,将其直接放入栈中。
4)读到“*”,弹出8和5,执行8*5,并将结果40压入栈中。而后过程类似,读到“+”,将40和5弹出,将40+5的结果45压入栈...以此类推。最后求的值288。
借鉴了高人的解题思路,自己不怎么表达的清楚
程序代码:
#include<iostream>
#include <cstdio>
#include<cstring>
#define N 100
using namespace std;
int calculate(char s[],int t,int n) //计算
{
if(n<t) return ;
if(n==t)
{
if(s[t]>='A' && s[t]<='Z') return (s[t]-'A');
else
if(s[t]>='a' && s[t]<='z') return (s[t]-'a');
else return s[t]-'';
}
int f1=-,f2=-; //f1 : '+' 或者是 '-'的位子;f2 : '*'的位子
int kuohao=;
for(int i=t;i<=n;i++)
{
if(s[i]=='(') kuohao++;
else
if(s[i]==')') kuohao--;
else
if((s[i]=='+' || s[i]=='-') && kuohao==) f1=i;
else
if(s[i]=='*' && kuohao==) f2=i;
}
if(f1< && f2<) return calculate(s,t+,n-);
if(f1>)
{
if(s[f1]=='+') return calculate(s,t,f1-)+calculate(s,f1+,n);
else return calculate(s,t,f1-)-calculate(s,f1+,n);
}
else return calculate(s,t,f2-)*calculate(s,f2+,n);
}
void g(char s[])
{ char *p=s;
char temp[N],*p1=temp; while(*p!='\0')
{
while(((*p==' ') ||(*p=='\t')) && (*p!='\0')) *p++;
*p1=*p;
p1++;
p++;
}
*p1='\0';
strcpy(s,temp);
}
int main()
{
int t;
scanf("%d",&t);getchar();
while(t--)
{
char str1[N],str2[N];
gets(str1);
gets(str2);
g(str1);
g(str2);
int a=calculate(str1,,strlen(str1)-);
int b=calculate(str2,,strlen(str2)-);
if(a==b)cout<<"YES\n";
else cout<<"NO\n";
}
return ;
}
数据结构——POJ 1686 Lazy Math Instructor 栈的应用的更多相关文章
- POJ 1686 Lazy Math Instructor(栈)
原题目网址:http://poj.org/problem?id=1686 题目中文翻译: Description 数学教师懒得在考卷中给一个问题评分,因为这个问题中,学生会为所问的问题提出一个复杂的公 ...
- POJ 1686 Lazy Math Instructor (模似题+栈的运用) 各种坑
Problem Description A math instructor is too lazy to grade a question in the exam papers in which st ...
- poj 1684 Lazy Math Instructor(字符串)
题目链接:http://poj.org/problem?id=1686 思路分析:该问题为表达式求值问题,对于字母使用浮点数替换即可,因为输入中的数字只能是单个digit. 代码如下: #includ ...
- Lazy Math Instructor
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3721 Accepted: 1290 Description A m ...
- UVALive 2056 Lazy Math Instructor(递归处理嵌套括号)
因为这个题目说明了优先级的规定,所以可以从左到右直接运算,在处理嵌套括号的时候,可以使用递归的方法,给定每一个括号的左右边界,伪代码如下: int Cal(){ if(括号) sum += Cal( ...
- POJ - 2183 Bovine Math Geniuses
“模拟“题,运用哈希,不断地按照一定运算规律对一个结果进行计算,如果重复出现就停止并且输出该数.注意到仔细看题,这种题一定要细心! POJ - 2183 Bovine Math Geniuses Ti ...
- 数据结构--线段树--lazy延迟操作
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53749 ...
- 数据结构录 之 单调队列&单调栈。
队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...
- 数据结构录 之 单调队列&单调栈。(转)
http://www.cnblogs.com/whywhy/p/5066306.html 队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇 ...
随机推荐
- 使用JavaScriptSerializer序列化集合、字典、数组、DataTable为JSON字符串 分类: 前端 数据格式 JSON 2014-10-30 14:08 169人阅读 评论(0) 收藏
一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大 ...
- 第一篇、Apache和Tomcat的整合
1.web架构 首先上图,解释web通用架构 通常情况下分为三大块 : ★ Web server : 通常情况下由 Apache Http Server . IBM Http Server .I ...
- There is no ID/IDREF binding for IDREF
http://blog.csdn.net/greensurfer/article/details/7596219
- 【原创】Git版本控制器的基本使用
关于git Git,是一个分布式版本控制软件.最初本是为了更好的管理Linux内核开发而被林纳斯·托瓦兹开发,后来因为项目开发中版本控制的强烈需求,而git也日趋成熟,最终成为了一个独立的版本控制软件 ...
- CGContextRef一点用法
quartz 是主要的描画接口,支持基于路径的描画.抗锯齿渲染.渐变填充模式.图像.颜色.坐标空间变换.以及PDF 文档的创建.显示.和分析.UIKit 为Quartz 的图像和颜色操作提供了Ob ...
- 关于UIScrollView属性和方法的总结
iOS中UIScollView的总结 在iOS开发中可以说UIScollView是所有滑动类视图的基础,包括UITableView,UIWebView,UICollectionView等等,UIScr ...
- javascript基础学习(八)
javascript之日期对象 学习要点: 日期对象 将日期对象转换为字符串 将日期对象中的日期和时间转换为字符串 日期对象中的日期 日期对象中的时间 设置日期对象中的日期 设置日期对象中的时间 与毫 ...
- linux定时器
我们常常有设置系统在某一时间执行相应动作的需求,比如设置电脑什么时候自动锁屏,什么时候自动关机,设置应用程序什么时候自动运行,什么时候自动退出.这些与时间相关的功能,都需要依靠操作系统中的定时器来实现 ...
- nodejs初体验
安装好nodejs之后 在命令行中直接运行:node -v //若安装成功则显示版本号 var http = require('http'); http.createServer(function ( ...
- script加defer="defer" 的意义
<script defer="defer">alert("页面加载完我才执行的")</script>先看到这段话 然后再执行上面的 JS ...