您的位置:首页 > 其它

2017计蒜之道 初赛 第二场 百度的科学计算器(简单)

2017-05-22 11:03 387 查看
/**
题目:2017计蒜之道初赛第二场百度的科学计算器(简单)
链接:https://nanti.jisuanke.com/t/15504
题意:给一个合法的表达式,包含加号+、减号-、括号()、数字常量,表达式中没有空格。
输入数据保证数字常量以及计算过程中数值绝对值均不超过10^12​​,对于浮点型数值常量,保证小数点后不超过6位。

思路:暴力模拟;python有函数可以直接调用。

坑点:如果表达式中出现过浮点数,那么输出结果保留6位小数,
否则输出整数,不出现小数。

*/

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
usingnamespacestd;
typedeflonglongLL;
constintmod=1e9+7;
constintmaxn=1e6+5;
constdoubleeps=1e-12;
charop[1005];
doublea[1004];
chars[1004];
intn;
intflag;
intmain()
{
while(scanf("%d",&n)==1)
{
scanf("%s",s);
flag=0;
intaz=0,pz=0;
intlen=strlen(s);
for(inti=0;i<len;){
LLin=0;
LLdt=0;
LLp=1;
if(s[i]>='0'&&s[i]<='9'){
while(i<len&&s[i]>='0'&&s[i]<='9'){
in=in*10+(s[i]-'0');
i++;
}
if(s[i]=='.'){
flag=1;
i++;
while(i<len&&s[i]>='0'&&s[i]<='9'){
dt=dt*10+(s[i]-'0');
i++;
p*=10;
}
}
doublex=in+1.0*dt/p;
a[az++]=x;
}else
{
if(s[i]=='-'){
op[pz++]='-';
i++;
continue;
}
if(s[i]=='+'){
i++;
op[pz++]='+';
continue;
}
if(s[i]=='('){
i++;
op[pz++]='(';
continue;
}
if(s[i]==')'){///左结合。找到左边的符号,以及左边的数,然后模拟计算过去。
intpl=pz-1;
while(op[pl]!='(')pl--;
inttemp=pl;//pz=tmep;

intcnt=pz-pl-1;
inttempa=az-cnt-1;
doublevalue=a[az-cnt-1];
for(intj=pl+1,k=az-cnt;j<pz;j++,k++){
if(op[j]=='+'){
value+=a[k];
}elsevalue-=a[k];
}

pz=temp;
az=tempa;
a[az++]=value;
i++;
continue;
}
}
}

doublevalue=a[0];///已处理所有括号,只有数和-,+符号。左结合计算。
for(intj=0,k=1;j<pz;j++,k++){
if(op[j]=='+'){
value+=a[k];
}elsevalue-=a[k];
}
if(flag)///如果出现过浮点数。
printf("%.6lf\n",value);
else
printf("%lld\n",(LL)value);
}
return0;
}

表达式树解法:可处理加减乘除都出现的情况。
思路:每次把最后进行的计算符号作为根。递归处理。


#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
usingnamespacestd;
typedeflonglongLL;
constintmod=1e9+7;
constintmaxn=1e3+5;
constdoubleeps=1e-12;
intlch[maxn],rch[maxn];
structnode
{
doublevalue;
charop;
}t[maxn];
intnc=0;
chars[maxn];
intisDouble;
intbuild_tree(char*s,intx,inty)///[x,y)
{
intc1=-1,c2=-1,p=0;
intu;
intsign=0;
for(inti=x;i<y;i++){
switch(s[i]){
case'(':p++;sign=1;break;
case')':p--;sign=1;break;
case'+':case'-':if(!p)c1=i;sign=1;break;///括号外的最后计算的+,-符号。
case'*':case'/':if(!p)c2=i;sign=1;break;///括号外的最后计算的*,/符号。
}
}
if(sign==0){///全是数字或者小数点。说明已经是叶子了。
doublein=0;
LLdt=0;
LLp=1;
while(x<y&&s[x]!='.'){
in=in*10+(s[x]-'0');
x++;
}
if(x<y&&s[x]=='.'){
x++;
isDouble=1;
while(x<y){
dt=dt*10+(s[x]-'0');
x++;
p=p*10;
}
}
u=++nc;
t[u].value=in+1.0*dt/p;
lch[u]=0;
rch[u]=0;
returnu;
}
if(c1<0)c1=c2;///没有加减符号.
if(c1<0)returnbuild_tree(s,x+1,y-1);///没有乘除符号,那么应该是被括号包含,去掉两边的括号。
u=++nc;
lch[u]=build_tree(s,x,c1);
rch[u]=build_tree(s,c1+1,y);
t[u].op=s[c1];
returnu;
}
doubledfs(introot)
{
if(lch[root]==0&&rch[root]==0){
returnt[root].value;
}
charop=t[root].op;
doublelans=dfs(lch[root]),rans=dfs(rch[root]);
switch(op){
case'+':returnlans+rans;
case'-':returnlans-rans;
case'*':returnlans*rans;
case'/':returnlans/rans;
}
return-1;
}
intmain()
{
intn;
while(scanf("%d",&n)==1)
{
scanf("%s",s);
nc=0;
isDouble=0;
introot=build_tree(s,0,strlen(s));///root=1
doubleans=dfs(root);
if(isDouble)printf("%.6lf\n",ans);///出现浮点数,输出6位小数,否则输出整数。
elseprintf("%lld\n",LL(ans));
}
return0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: