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数据结构专题:N - 秋实大哥搞算数

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

【CDOJ 1074】秋实大哥搞算术【栈计算表达式】

地址http://acm.uestc.edu.cn/#/problem/show/1074 #include #include #include #inclu...

[UESTC 1074]秋实大哥搞算数

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

秋实大哥搞算数(字符串模拟)

N - 秋实大哥搞算数 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Oth...

CDOJ 1147 秋实大哥带我飞 最短路径条数 dijkstra就可搞

啊,就是说给你一个图,让你求从1到n的最短路径条数,模1e9+7 图的边权可能为0或者正数,边和点都可以重复走 最短路径条数为无穷则输出-1 啊,那个边权全为正的情况好说,边和点也不可能重复走 就是如...

CDOJ_1063 秋实大哥与妹纸(堆结构)

秋实大哥与妹纸 致中和,天地位焉,万物育焉。秋实大哥是一个追求中庸的人。 虽然秋实大哥的仰慕者众多,但秋实大哥不喜欢极端的妹纸。所以他想从所有仰慕自己的妹纸中挑选出一个符合中庸之道的。 ...

cdoj 2015数据结构专题:D - 秋实大哥与战争

男儿何不带吴钩,收取关山五十州。 征战天下是秋实大哥一生的梦想,所以今天他又在练习一个对战游戏。 秋实大哥命令所有士兵从左到右排成了一行来抵挡敌人的攻击。 敌方每一次会攻击一个士兵,这个士兵就会阵亡,...

cdoj1057 秋实大哥与花 线段树 区间加,区间查询和

题目链接:http://acm.uestc.edu.cn/#/problem/show/1057题意:题解:代码:#include using namespace std; typedef long...
  • yxg_123
  • yxg_123
  • 2017年03月01日 22:24
  • 75

cdoj 2015数据结构专题:H - 秋实大哥打游戏

”也许人生就是游戏,你却执意耕耘着春秋。” —— 秋实大哥叹道。 秋实大哥是一个喜欢玩游戏的人,相较于其他种类的游戏,秋实大哥更喜欢自由开放的沙盒游戏,尤其是minecraft。 现在,秋实大哥发...

CDOJ1057-秋实大哥与花

秋实大哥与花 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CDOJ 1074 秋实大哥搞算数(栈_表达式求值)
举报原因:
原因补充:

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