题目:
分析:
众所周知,在一个只有加法和乘法的算式里,如果可以任意加括号,那么结果最大就是先算加法再算乘法,最小就是先算乘法再算加法。那么,这道题就很简单了。我们可以用两个栈maxs和mins分别用来计算最大值和最小值,再有两个变量maxres和minres,分别表示最大值和最小值。由于数据较大,所以数的类型应该为__int64,并且要对870764322取膜,为了方便,我们把870764322设为符号常量N。接下来只要牢记最大值是先算加法,最小值是先算乘法就好了。我们可以从左往右遍历一遍字符串,如果遇到数字,就将该数字分别放进maxs和mins。如果遇到‘+’,即str[i]'+',这时maxs和mins要兵分两路,最小值要先算乘法,加法先不算,所以mins直接进栈‘+’的下一个元素(即str[++i])就行,而最大值要先算加法,所以要把maxs栈顶元素和str[i]相加(注意,由于前面已经++i,所以这时的str[i]就是‘+’的下一个元素)。同理,当遇到str[i]‘*’时,maxs直接进栈元素str[++i],mins的栈顶元素和str[i]相乘。最后把maxs里的所有元素相乘即为最大值,把mins里的所有元素相加即为最小值。下面通过一个例子来具体说明。
例如:输入 1 + 2 * 3 + 4 * 5
- str[0]==' 1 ' , 直接进栈,maxs={1} , mins={1}
- str[1]' + ' , str[++i]' 2 ' , maxs={3}(1+2=3,栈顶为3) , mins={1,2}(2直接进栈,栈顶为2)
- str[3]' * ' , str[++i]' 3 ' , maxs={3,3}(3直接进栈,栈顶为3) , mins={1,6}(2 * 3=6,栈顶为6)
- str[5]' + ' , str[++i]' 4 ' , maxs={3,7}(3+4=7,栈顶为7) , mins={1,6,4}(4直接进栈,栈顶为4)
- str[7]' * ' , str[++i]' 5 ' , maxs={3,7,5}(5直接进栈) , mins={1,6,20}(4 * 5=20,栈顶为20)
- 遍历完成,maxres = 3 * 7 * 5 = 105 , minres = 1 + 6 + 20 = 27
(PS:此处只是对过程进行演示,对N取膜等细节处理并未体现,大家自己注意)
代码:
#include<iostream>
#include<stack>
#include<string>
using namespace std;
#define N 870764322 //设置符号常量N
int main()
{
int i, n;
__int64 res;
string str;
stack<__int64>maxs;
stack<__int64>mins;
cin >> str;
n = str.size();
for (i = 0; i<n; i++)
{
if ('0'<str[i] && str[i] <= '9') //遇到数字
{
maxs.push(str[i] - '0'); //直接进栈
mins.push(str[i] - '0');
}
else if (str[i] == '+') //遇到“+”
{
mins.push(str[++i]-'0'); //'+'的下个数直接进栈,最后再算(最小值)
res=(maxs.top()+(str[i]-'0'))%N; //先算加法 (最大值)
maxs.pop();
maxs.push(res);
}
else //遇到“*”
{
maxs.push(str[++i]-'0'); //'*'的下个数直接进栈,最后再算(最大值)
res=(mins.top()*(str[i]-'0'))%N; //先算乘法(最小值)
mins.pop();
mins.push(res);
}
}
__int64 maxres=1,minres=0;
while(!maxs.empty()) //再算乘法(最大值)
{
maxres*=maxs.top();
maxres%=N;
maxs.pop();
}
while(!mins.empty()) //再算加法(最小值)
{
minres+=mins.top();
minres%=N;
mins.pop();
}
printf("%I64d
%I64d
",maxres,minres);
return 0;
}