zoukankan      html  css  js  c++  java
  • 2017计蒜之道 初赛 第二场 百度的科学计算器(简单)

    /**
    题目:2017计蒜之道 初赛 第二场 百度的科学计算器(简单)
    链接:https://nanti.jisuanke.com/t/15504
    题意:给一个合法的表达式,包含加号+、减号-、括号()、数字常量,表达式中没有空格。
    输入数据保证数字常量以及计算过程中数值绝对值均不超过 10^12​​,对于浮点型数值常量,保证小数点后不超过 6位。
    
    思路:暴力模拟;python有函数可以直接调用。
    
    坑点:如果表达式中出现过浮点数,那么输出结果保留6位小数,
    否则输出整数,不出现小数。
    
    */
    
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int mod=1e9+7;
    const int maxn=1e6+5;
    const double eps = 1e-12;
    char op[1005];
    double a[1004];
    char s[1004];
    int n;
    int flag;
    int main()
    {
        while(scanf("%d",&n)==1)
        {
            scanf("%s",s);
            flag = 0;
            int az = 0, pz = 0;
            int len = strlen(s);
            for(int i = 0; i < len; ){
                LL in = 0;
                LL dt = 0;
                LL p = 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;
                        }
                    }
                    double x = 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]==')'){///左结合。找到左边的符号,以及左边的数,然后模拟计算过去。
                        int pl = pz-1;
                        while(op[pl]!='(') pl--;
                        int temp = pl;// pz = tmep;
    
                        int cnt = pz-pl-1;
                        int tempa = az-cnt-1;
                        double value = a[az-cnt-1];
                        for(int j = pl+1, k = az-cnt; j < pz; j++,k++){
                            if(op[j]=='+'){
                                value += a[k];
                            }else value -= a[k];
                        }
    
                        pz = temp;
                        az = tempa;
                        a[az++] = value;
                        i++;
                        continue;
                    }
                }
            }
    
    
            double value = a[0];///已处理所有括号,只有数和-,+符号。左结合计算。
            for(int j = 0, k = 1; j < pz; j++,k++){
                if(op[j]=='+'){
                    value += a[k];
                }else value -= a[k];
            }
            if(flag)///如果出现过浮点数。
                printf("%.6lf
    ",value);
            else
                printf("%lld
    ",(LL)value);
        }
        return 0;
    }




    表达式树解法:可处理加减乘除都出现的情况。
    思路:每次把最后进行的计算符号作为根。递归处理。
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int mod=1e9+7;
    const int maxn=1e3+5;
    const double eps = 1e-12;
    int lch[maxn], rch[maxn];
    struct node
    {
        double value;
        char op;
    }t[maxn];
    int nc = 0;
    char s[maxn];
    int isDouble;
    int build_tree(char *s,int x,int y)///[x, y)
    {
        int c1 = -1, c2 = -1, p = 0;
        int u;
        int sign = 0;
        for(int i = 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){///全是数字或者小数点。说明已经是叶子了。
            double in = 0;
            LL dt = 0;
            LL p = 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;
            return u;
        }
        if(c1<0) c1 = c2;///没有加减符号.
        if(c1<0) return build_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];
        return u;
    }
    double dfs(int root)
    {
        if(lch[root]==0&&rch[root]==0){
            return t[root].value;
        }
        char op = t[root].op;
        double lans = dfs(lch[root]), rans = dfs(rch[root]);
        switch(op){
        case '+': return lans+rans;
        case '-': return lans-rans;
        case '*': return lans*rans;
        case '/': return lans/rans;
        }
        return -1;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)==1)
        {
            scanf("%s",s);
            nc = 0;
            isDouble = 0;
            int root = build_tree(s,0,strlen(s));/// root=1
            double ans = dfs(root);
            if(isDouble) printf("%.6lf
    ",ans);///出现浮点数,输出6位小数,否则输出整数。
            else printf("%lld
    ",LL(ans));
        }
        return 0;
    }

     
  • 相关阅读:
    Win10解决RuntimeBroker.exe后台运行CPU占比高的方法
    easyexcel测试用例
    电脑Wlan不能上网的解决办法
    [LeetCode] Delete and Earn 删除与赚取
    [LeetCode] Daily Temperatures 日常温度
    [LeetCode] 738. Monotone Increasing Digits 单调递增数字
    [LeetCode] 737. Sentence Similarity II 句子相似度之二
    [LeetCode] Parse Lisp Expression 解析Lisp表达式
    [LeetCode] Asteroid Collision 行星碰撞
    [LeetCode] 644. Maximum Average Subarray II 子数组的最大平均值之二
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/6888501.html
Copyright © 2011-2022 走看看