CDOJ 1074 秋实大哥搞算数(栈_表达式求值)

原创 2015年07月08日 20:47:04

秋实大哥搞算数

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
秋实大哥大学物理挂科了,于是在下学期的前两周的某一天要悲剧的补考。为了不给学校的挖掘机大楼做贡献,秋实大哥决定在假期里努力复习。当然,良好的计算能力也是非常必要的,毕竟是涉及计算自己做多少分的题能够通过考试的问题。现在他给自己出了一大堆长长的只有涉及整形四则运算式子,然后埋头计算结果。为了检验自己的计算能力,他请你来帮忙。

Input

第一行一个整数T,表示式子的总数。

接下来每一行有一个长度不超过10^6的表达式,只包含正整数和四则运算符号('+', '-', '*', '/')。

保证输入合法。

Output

对于每一个表达式,输出相应的结果,占一行。

保证运算及结果在long long范围以内。

Sample input and output

Sample Input Sample Output
2
12+5/4-1
4*5/3
12
6


首先,思想就是两个栈(后进先出)嘛,一个栈存放运算符,一个栈存放数。怎么用栈呢?

为了方便知道表达式是否结束,在输入了这个表达式后,我又在后面加了一个'='。

最先输入的肯定是数,然后是运算符,因此,就判断:

第一个运算符入栈时,

肯定还不能运算(注意

因为不知道后面的情况。

(一定要切记你的程序里什么时候能运算,什么时候不能运算,要把不能运算的条件都记录下来,因为在读到'='时就准备要输出了,所以在读到等号后要让你的程序把式子都运算完,楼主就是在这WA了好久,当时没有形成严密清晰的思维…嗯,这个习惯不好

第二个运算符运算时,分情况讨论:

如果第二个运算符是*或/,

如果前面的运算符是*或/,则将前面的运算符进行运算

如果用栈的思想来描述就是,上一个运算符出栈(当前这个运算符还没进栈),上两个数出栈,然后进行运算,新得到的数入栈。

否则不进行运算(注意!)。

如果第二个运算符是+或-,

则将前面的运算符运算(栈的思想同上)。

第三个运算符及其以后的情况同第二个运算符

好,我们现在来数数不能运算的情况

首先,按运算符分类,0个运算符的时候,即第一个运算符读到的是'=',特判一下,直接输出第一个数就好。

1个运算符的时候,第二个运算符读到的是'=',即是读到'=',就把前一个运算符运算,然后输出。

2个运算符的时候,如果第二个是+或-,运算后只剩1个运算符,同第二种情况,

如果第二个是*或/,则读到'='时,需要进行两次运算,然后输出。

>=3个运算符时,同2个运算符的情况。

接下来我们来说为什么>=3个运算符的情况同第二个运算符的情况。

首先,如果你当前要入栈的运算符是+或-,则前面的式子的值就可以直接算出来了。

如果你当前入栈的是*或/,则前面的那个是+或-时不运算,前面那个是*或/时就可以运算,因此,最多,你遇到*或/后前面有个+或-,这时,运算符栈中有两个运算符。

也就是说,在你运算的过程中,新的运算符入栈后,栈中存有一个或两个运算符。

因此在+或-运算时,可能会有一次或者两次运算(两次的话,先算后面的乘除,再算前面的加减)。

在读到’=‘时也是同进行+或-的情况。

所以我的代码中(懒得用函数了,直接手写的),有两种运算,只进行一次的运算和进行到栈中只有一个运算符(当前读到的这个运算符入栈了)的运算。


遇到的错误:1,RE,貌似是数据中有空行,嗯,改了输入条件就好了,反正这块很迷,用%s应该就没事哈,不过我加了一个如果当前输入后的字符串的第一个字符还是空,好像并没有什么卵用,%s不会读入空格的啊,反正很迷,不管它了

2,就是我在读到’=‘时只进行了一次计算,然后有可能前面有两个运算符,所以就WA了半天。

3,T了几发,memset给T掉了,memset也不能随便用啊…


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 1000060
char express[maxn];
char ope[10];
long long num[10];
int main()
{
	int t;
	scanf("%d%*c", &t);
//	cin >> t; getchar();
	while (t--)
	{
//		memset(express, 0, sizeof(express));
		memset(ope, 0, sizeof(ope));
		memset(num, 0, sizeof(num));
		scanf("%s", express);
		if (express[0] == '\0')
		{
			t++; continue;
		}
/*		char ch;
		int len = 0;
		while (1)
		{
			ch = getchar();
			if (ch == '\n')
				break;
			else
			if ((ch >= '0'&&ch <= '9') || ch == '+' || ch == '-' || ch == '*' || ch == '/')
			{
				express[len] = ch; len++;
			}
		}
		if (len == 0)
		{
			t++;
			continue;
		}
*/		
		int n = strlen(express);
		express[n++] = '='; express[n] = '\0';
		long long ans = 0;
		long long n_ope = 0, n_num = 0;
		for (int i = 0; i < n; i++)
		{
			if (express[i] >= '0'&&express[i] <= '9')
			{
				long long temp1, temp2;
				temp1 = num[n_num] * 10;
				temp2 = express[i] - '0';
				num[n_num] = temp1 + temp2;
			}
			else if (express[i] == '+' || express[i] == '-' || express[i] == '*' || express[i] == '/' || express[i] == '=')
			{
				n_num++; ope[n_ope++] = express[i];
				if (n_ope == 1)
				{
					if (ope[n_ope - 1] == '=')
					{
						ans = num[0]; break;
					}
				}
				else if (n_ope>1)
				{
					if (ope[n_ope - 1] == '+' || ope[n_ope - 1] == '-')
					{
						while (n_ope > 1)
						{
							switch (ope[n_ope - 2])
							{
							case'+':
								num[n_num - 2] = num[n_num - 2] + num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'-':
								num[n_num - 2] = num[n_num - 2] - num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'*':
								num[n_num - 2] = num[n_num - 2] * num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'/':
								if (num[n_num - 1] == 0)
								{
									printf("divisor is 0\n");
									return 0;
								}
								num[n_num - 2] = num[n_num - 2] / num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							default:
								break;
							}
						}
					}
					else if (ope[n_ope - 1] == '*' || ope[n_ope - 1] == '/')
					{
						if (ope[n_ope - 2] == '*')
						{
							num[n_num - 2] = num[n_num - 2] * num[n_num - 1];
							ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
							num[n_num - 1] = 0; n_num--;
						}
						else if (ope[n_ope - 2] == '/')
						{
							if (num[n_num - 1] == 0)
							{
								printf("divisor is 0\n");
								return 0;
							}
							num[n_num - 2] = num[n_num - 2] / num[n_num - 1];
							ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
							num[n_num - 1] = 0; n_num--;
						}
					}
					else if (ope[n_ope - 1] == '=')
					{
						while (n_ope > 1)
						{
							switch (ope[n_ope - 2])
							{
							case'+':
								num[n_num - 2] = num[n_num - 2] + num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'-':
								num[n_num - 2] = num[n_num - 2] - num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'*':
								num[n_num - 2] = num[n_num - 2] * num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'/':
								if (num[n_num - 1] == 0)
								{
									printf("divisor is 0\n");
									return 0;
								}
								num[n_num - 2] = num[n_num - 2] / num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							default:
								break;
							}
						}
						ans = num[0];
					}
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

cdoj 2015数据结构专题:M - 秋实大哥与线段树

“学习本无底,前进莫徬徨。” 秋实大哥对一旁玩手机的学弟说道。 秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构。 为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来...
  • isinfonia
  • isinfonia
  • 2015年05月20日 00:07
  • 238

UESTC -- 1074 秋实大哥搞算数 (栈)

题目大意:给出一串只涉及整形加减乘除四则运算式子,求出式子的结果。 思路分析:运用两个栈,一个用来存数字,一个用来存加减乘除运算符,从头到尾扫描字符串,把数字存入数字栈,再看运算符,如果是第一个运算符...
  • u011346442
  • u011346442
  • 2015年05月26日 09:04
  • 345

算术表达式求值(顺序栈实现)

一.问题描述
  • zhaishaojiang
  • zhaishaojiang
  • 2014年10月12日 14:41
  • 2570

栈的应用之算术表达式求值

栈是一种后进先出的数据结构。表达式求值是对栈的一个典型的应用。 对于如下一个表达式: 1 + 2 * (3 + 4) 此算术表达式由一些操作符和操作数组成。其中,操作符有‘+’、‘*’、‘(...
  • zjdnwpu
  • zjdnwpu
  • 2016年04月28日 22:12
  • 3902

2016 UESTC Training for Data Structures N - 秋实大哥搞算数 CDOJ 1074 栈 表达式求值

N - 秋实大哥搞算数 给一个表达式,无括号,保证合法,long long以内,整数运算,求值 栈 表达式求值的经典问题, 首先设置一个开始和结束符号#,他们的优先级是最低的,然后开两个栈,...
  • code12hour
  • code12hour
  • 2016年05月01日 14:38
  • 244

双栈算术表达式求值算法

import java.util.Scanner; /** * (1+((2+3)*(4*5)))测试 * Created by lizhaoz on 2016/1/8. */ public...
  • li563868273
  • li563868273
  • 2016年01月08日 14:45
  • 1011

数据结构Java实现——①栈-->栈的应用三、算术表达式求值

当一个算术表达式中含有多个运算符,且运算符的优先级不同的情况下,如何才能处理一个算术表达式????? 2、思路 首先我们要知道表达式分为三类: ①中缀表达式:a+(b-c/d)*e ②前缀表达...
  • u011446177
  • u011446177
  • 2015年01月04日 12:44
  • 2945

[UESTC 1074]秋实大哥搞算数

秋实大哥大学物理挂科了(误),于是在下学期的前两周的某一天要悲剧的补考。为了不给学校的挖掘机大楼做贡献,秋实大哥决定在假期里努力复习。当然,良好的计算能力也是非常必要的,毕竟是涉及计算自己做多少分的题...
  • dxyinme
  • dxyinme
  • 2016年10月03日 10:56
  • 213

Dijkstra的双栈算术表达式求值算法

注:不考虑乘除优先级,使用括号确定计算顺序 public static double evaluate(String inStr) { Stack ops = new Sta...
  • moshenglv
  • moshenglv
  • 2016年07月05日 20:04
  • 901

javascript栈的应用之表达式求值

下面来谈一个比较经典的表达式求值问题,这个问题主要是设计到操作符的优先级。我们通常看到的表达式都是中缀表达式,存在很多优先级差别,而后缀表达式则没有这些优先级问题。下面先看看两种表达式的区别。 ...
  • mevicky
  • mevicky
  • 2015年05月12日 23:31
  • 780
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CDOJ 1074 秋实大哥搞算数(栈_表达式求值)
举报原因:
原因补充:

(最多只允许输入30个字)