Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 10 Accepted Submission(s) : 8
Problem Description
Have you used #define in C/C++ code like the code below?
#include <stdio.h>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
int main()
{
printf("%d\n" , MAX(2 + 3 , 4));
return 0;
}
Run the code and get an output: 5, right?
You may think it is equal to this code:
#include <stdio.h>
int max(a , b) { return ((a) > (b) ? (a) : (b)); }
int main()
{
printf("%d\n" , max(2 + 3 , 4));
return 0;
}
But they aren't.Though they do produce the same anwser , they work in two different ways.
The first code, just replace the MAX(2 + 3 , 4) with ((2 + 3) > (4) ? (2 + 3) : 4), which calculates (2 + 3) twice.
While the second calculates (2 + 3) first, and send the value (5 , 4) to function max(a , b) , which calculates (2 + 3) only once.
What about MAX( MAX(1+2,2) , 3 ) ?
Remember "replace".
First replace: MAX( (1 + 2) > 2 ? (1 + 2) : 2 , 3)
Second replace: ( ( ( 1 + 2 ) > 2 ? ( 1 + 2 ) : 2 ) > 3 ? ( ( 1 + 2 ) > 2 ? ( 1 + 2 ) : 2 ) : 3).
The code may calculate the same expression many times like ( 1 + 2 ) above.
So #define isn't good.In this problem,I'll give you some strings, tell me the result and how many additions(加法) are computed.
#include <stdio.h>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
int main()
{
printf("%d\n" , MAX(2 + 3 , 4));
return 0;
}
Run the code and get an output: 5, right?
You may think it is equal to this code:
#include <stdio.h>
int max(a , b) { return ((a) > (b) ? (a) : (b)); }
int main()
{
printf("%d\n" , max(2 + 3 , 4));
return 0;
}
But they aren't.Though they do produce the same anwser , they work in two different ways.
The first code, just replace the MAX(2 + 3 , 4) with ((2 + 3) > (4) ? (2 + 3) : 4), which calculates (2 + 3) twice.
While the second calculates (2 + 3) first, and send the value (5 , 4) to function max(a , b) , which calculates (2 + 3) only once.
What about MAX( MAX(1+2,2) , 3 ) ?
Remember "replace".
First replace: MAX( (1 + 2) > 2 ? (1 + 2) : 2 , 3)
Second replace: ( ( ( 1 + 2 ) > 2 ? ( 1 + 2 ) : 2 ) > 3 ? ( ( 1 + 2 ) > 2 ? ( 1 + 2 ) : 2 ) : 3).
The code may calculate the same expression many times like ( 1 + 2 ) above.
So #define isn't good.In this problem,I'll give you some strings, tell me the result and how many additions(加法) are computed.
Input
The first line is an integer T(T<=40) indicating case number. The next T lines each has a string(no longer than 1000), with MAX(a,b), digits, '+' only(Yes, there're no other characters). In MAX(a,b), a and b may be a string with MAX(c,d), digits, '+'.See the sample and things will be clearer.
Output
For each case, output two integers in a line separated by a single space.Integers in output won't exceed 1000000.
Sample Input
6 MAX(1,0) 1+MAX(1,0) MAX(2+1,3) MAX(4,2+2) MAX(1+1,2)+MAX(2,3) MAX(MAX(1+2,3),MAX(4+5+6,MAX(7+8,9)))+MAX(10,MAX(MAX(11,12),13))
Sample Output
1 0 2 1 3 1 4 2 5 2 28 14
这是一道表达式求值问题,模拟题。题目意思就是MAX计算加法的次数其实是比较时进行了一次,返回时又进行了一次。例如:MAX(3+2,4)其实是进行了两次加法。
解题思路:
表达式求值要用到数据结构中的中缀转后缀计算表达式。这就要借助栈来将中缀转为后缀表达式。然后在计算加法的次数即可。本题的关键就在于表达式的中缀转后缀。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <cstring>
#include <sstream>
using namespace std;
string S1,S2;///S1为中缀表达式,S2为中缀转化为后缀的表达式
struct Num
{
int numb;
int time;
};
int change(double d)///计算各位数字之和
{
int sum=0;
ostringstream o;
string c;
if(o<<d)
c=o.str();
for(int i=0;i<c.size();i++)
{
if(c[i]>='0'&&c[i]<='9')
sum+=c[i]-'0';
}
return sum;
}
/**
代码的核心就是定义各个运算符的优先级,通过优先级来将其中缀表达式转化为后缀表达式,进行运算。
**/
int level(char a)///定义运算符的优先级
{
int flag;
switch(a)
{
case ',':flag=1;break;
case 'S':flag=4;break;
case 'M':flag=4;break;
case '+':flag=2;break;
case '-':flag=2;break;
case '*':flag=3;break;
case '/':flag=3;break;
default :flag=0;
}
return flag;
}
void conversion()///中缀转后缀
{
stack<char>Q;
char a;
a='#';
Q.push(a);
int i=0,m=S1.length();
while(i<m)
{
a=Q.top();
if(S1[i]=='(')
{
Q.push(S1[i]);i++;
}
else if(S1[i]==')')
{
while(a!='(')
{
S2=S2+a+'#';Q.pop();a=Q.top();
}
Q.pop();i++;
}
else if(S1[i]=='+'||S1[i]=='-'||S1[i]=='*'||S1[i]=='/'||S1[i]=='S'||S1[i]=='M'||S1[i]==',')
{
while(level(a)>=level(S1[i]))
{
S2=S2+a+'#';Q.pop();a=Q.top();
}
if(S1[i]=='S')
{
Q.push(S1[i]);i+=4;
}
else if(S1[i]=='M')
{
Q.push(S1[i]);i+=3;
}
else if(S1[i]==',')
{
i++;
}
else
{
Q.push(S1[i]);i++;
}
}
else
{
while((S1[i]>='0'&&S1[i]<='9')||S1[i]=='.')
{
S2=S2+S1[i];i++;
}
S2+='#';
}
}
while(!Q.empty())
{
a=Q.top();
Q.pop();
if(a!='#')
{
S2=S2+a+'#';
}
}
// cout<<S2<<endl;///查看中缀转后缀的结果
}
void calculate()///后缀进行值运算
{
int m=S2.length();
int i=0;
Num a,b,N;
stack<Num>W;
int num=0,num1=1;
while(i<m)
{
switch(S2[i])///计算以后将得到的结果入栈
{
case '+':
{
a=W.top();W.pop();
b=W.top();W.pop();
a.numb=a.numb+b.numb;
a.time=a.time+b.time+1;
W.push(a);
i++;break;
}
case 'M':
{
a=W.top();W.pop();
b=W.top();W.pop();
if(a.numb>=b.numb)
{
a.time=a.time*2+b.time;
W.push(a);
i++;break;
}
else
{
b.time=b.time*2+a.time;
W.push(b);
i++;break;
}
}
default:///对数字进行处理
{
if(S2[i]>='0'&&S2[i]<='9'&&num1==1)
{
num=num*10+S2[i]-'0';
if((S2[i+1]<'0')||(S2[i+1]>'9'))
{
N.numb=num;
N.time=0;
W.push(N);
}
}
else
{
num1=1;
num=0;
}
i++;
}
}
}
printf("%d %d\n",W.top().numb,W.top().time);///按题目要求定义输出格式
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cin>>S1;
S2="";
conversion();
calculate();
}
return 0;
}