zoukankan      html  css  js  c++  java
  • 栈-表达式求值 NOIP2013 P2

    【NOIP2013普及组P2】表达式求值

    Time Limit:10000MS  Memory Limit:128000K
    Total Submit:37 Accepted:19
    Case Time Limit:1000MS

    Description

    给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。

    Input

    输入仅有一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘法运算符“*”,且没有括号.
    所有参与运算的数字均为0到2^31-1之间的整数。输入数据保证这一行只有0~9、+、*这12种字符。

    Output

    输出只有一行,包含一个整数,表示这个表达式的值。注意:当答案长度多于4位时,请只输出最后4位,前导0不输出。

    Sample Input

    【样例1】
    1+1*3+4
    【样例2】
    1+1234567890*1
    【样例3】
    1+1000000003*1

    Sample Output

    【样例1】
    8
    【样例2】
    7891
    【样例3】
    4

    Hint

    【样例说明】
    样例1计算的结果为8,直接输出8。
    样例2计算的结果为1234567891,输出后4位,即7891。
    样例3计算的结果为1000000004,输出后4位,即4。

    【数据范围】
    对于30%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100;
    对于80%的数据,0≤表达式中加法运算符和乘法运算符的总数≤1000;
    对于100%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100000。

    Source

    中缀表达式求值——用两个栈 sign[] 和 num[] 分别存储符号和数字。


    当读入的字符是数字的时候:

    用 tt 表示当前读到的单个数字,则 number = number * 10 + tt

    当读入的字符是符号的时候:

    1.此时可以保证之前读入的一个完整数字 number 已经可以放入 num 栈当中了, 即 num[++topn] =number ;并将 number 赋值为 0 ,便于下次正确读入一个完整数字;

    2.

    a.)如果当前读到的运算符优先级低于或等于前一个(即 sign 栈顶)运算符优先级,则前面读到的两个数(num[topn - 1] 和 num[topn])可以进行运算,并把运算后的结果直接替代到 num[topn - 1] ——举个例子,对于这个式子 3 * 2 + 1 ,当读入到加号的时候便可以把式子从 3 * 2 + 变化为 6 + 了;

    b.)如果当前读入的运算符优先级大于之前读入的运算符,则正常压入符号栈 sign 当中;


    请注意,当我们这样完整地一边读入一边处理完一个式子之后,此时的简化后的式子一定满足:前面的运算符优先级小于等于后面(即运算符升序排列)——这是因为如果读入时一个式子优先级大于等于后面的运算符,则已经被提前计算并化简成一个数字,比如 3 * 2 + 1 ,在读入加号时便把 3 * 2 化为 6 了。

    既然此时的式子满足这样一个顺序(运算符升序排列),我们只要从后往前把式子算一遍就可以得出表达式的值了。

    写到这里,程序框架已经很清晰了;当然,针对于题目而言自然有一些相应的细节。比如,这道题当中只要求输出最后 4 位,所以运算过程当中是可以随时取模 10000(=10^4) 的(实际上也需要这么做,因为尽管每个数不会超过 2^31 - 1 ,但它们的积或和就不一定了,是很有可能爆 long long int 的)。


    附上一份代码。

     1 #include <cstdio>
     2 long long int num[100005];
     3 char sign[100005], temp[4];
     4 int lv[100005], signlv[260];
     5 int topn, tops;
     6 long long int number;
     7 
     8 long long int f(char s)
     9 {
    10     switch (s) {
    11     case '+':
    12         return (num[topn] + num[topn + 1]) % 10000;
    13     case '*':
    14         return (num[topn] * num[topn + 1]) % 10000;
    15     default:
    16         return -1;
    17     }
    18     return -1;
    19 }
    20 
    21 void init()
    22 {
    23     lv[0] = -1;
    24     signlv['+'] = 1;
    25     signlv['*'] = 2;
    26     return ;
    27 }
    28 
    29 void solve()
    30 {
    31     char tt;
    32     while ((tt = getchar()) != '
    ') {
    33         switch (tt) {
    34         case '+':
    35         case '*': {
    36             num[++topn] = number;
    37             number = 0;
    38             if (lv[tops] < signlv[tt])
    39                 ++tops;
    40             else
    41                 num[--topn] = f(sign[tops]);
    42             sign[tops] = tt;
    43             lv[tops] = signlv[tt];
    44             break;
    45         }
    46         default: {
    47             number = number * 10 + tt - '0';
    48             break;
    49         }
    50         }
    51     }
    52     num[++topn]= number;
    53     while (tops)
    54         num[--topn] = f(sign[tops--]);
    55     return ;
    56 }
    57 
    58 void output()
    59 {
    60     bool flag = false;
    61     temp[0] = num[1] % 10;
    62     temp[1] = (num[1] /= 10) % 10;
    63     temp[2] = (num[1] /= 10) % 10;
    64     temp[3] = (num[1] /= 10) % 10;
    65     if (!temp[0] && !temp[1] && !temp[2] && !temp[3]) {
    66         putchar('0');
    67         putchar('
    ');
    68         return ;
    69     }
    70     if (temp[3] || flag) {
    71         putchar(temp[3] + '0');
    72         flag = true;
    73     }
    74     if (temp[2] || flag) {
    75         putchar(temp[2] + '0');
    76         flag = true;
    77     }
    78     if (temp[1] || flag) {
    79         putchar(temp[1] + '0');
    80         flag = true;
    81     }
    82     if (temp[0] || flag)
    83         putchar(temp[0] + '0');
    84     putchar('
    ');
    85     return ;
    86 }
    87 
    88 int main()
    89 {
    90     init();
    91     solve();
    92     output();
    93     return 0;
    94 }
    ghcred's Code
  • 相关阅读:
    智能聊天机器人——基于RASA搭建
    十分钟学会写shell脚本
    浅谈并发并行异步同步
    C/S系统实现两数求和(非阻塞+epoll+心跳包检测用户在线状况+滚动日志+配置文件.)
    编程之美第一篇 01分数规划
    欧拉函数
    奇妙的算法之LCS妙解
    N种方法妙讲LIS算法
    基于FeignClient提供简单的用户查询服务
    SpringCloud简介
  • 原文地址:https://www.cnblogs.com/ghcred/p/5716904.html
Copyright © 2011-2022 走看看