ACM-ICPC 2018 沈阳赛区网络预赛.Call of Accepted(中缀表达式转为后缀表达式计算)

You and your friends are at the table, playing an old and interesting game - the Call of Cthulhu.

There is a mechanism in the game: rolling the dice. You use a notation to communicate the type of dice that needs to be rolled - the operator "\mathop{\rm d}d". "x\mathop{\rm d}yxdy" means that an yy-sided dice should be rolled xx times and the sum of the results is taken.

Formally, for any two integers x, yx,y satisfying x \geq 0x≥0 and y \geq 1y≥1 , "x\mathop{\rm d}yxdy" means the sum of xx random integers in the range of [1, y][1,y]. It's obvious that either x < 0x<0 or y < 1y<1 makes the expression x\ {\rm d}\ yx d y illegal. For example: "2\mathop{\rm d}62d6" means that rolling a 66-sided dice 22 times. At this time, the result can be at least [1, 1] = 2[1,1]=2, and at most [6, 6] = 12[6,6]=12. The results of rolling can be used extensively in many aspects of the game. For example, an "1\mathop{\rm d}1001d100" can be used to determine whether an action with a percentage probability is successful, and a "3\mathop{\rm d}6+33d6+3 * 22" can be used to calculate the total damage when being attacked by 33 monsters simultaneously. In particular, the precedence of "\mathop{\rm d}d" is above "*". Since the operator "\mathop{\rm d}d" does not satisfy the associative law, it's necessary to make sure that "\mathop{\rm d}d" is right-associative.

Now the game has reached its most exciting stage. You are facing the Great Old One - Cthulhu. Because the spirit has been greatly affected, your sanity value needs to be deducted according to the result of rolling. If the sanity value loses too much, you will fall into madness. As a player, you want to write a program for knowing the minimum and maximum loss of sanity value before rolling, in order to make a psychological preparation.

The oldest and strongest emotion of mankind is fear, and the oldest and strongest kind of fear is fear of the unknown. ----H. P. Lovecraft

Input

There are multiple sets of input, at most 3030 cases.

Each set of input contains a string of only '+''-''*''d''('')' and integers without spaces, indicating the expression of this sanity loss. The length of the expression will be at most 100100.

It is guaranteed that all expressions are legal, all operators except for '(' and ')' are binary, and all intermediate results while calculating are integers in the range of [-2147483648, 2147483647][−2147483648,2147483647].

The most merciful thing in the world, I think, is the inability of the human mind to correlate all its contents. We live on a placid island of ignorance in the midst of black seas of infinity, and it was not meant that we should voyage far. ----H. P. Lovecraft

Output

For each set of data, output a line of two integers separated by spaces, indicating the minimum and maximum possible values of the sanity loss.

题目大意:现在给你一个表达式,其中包含的有数字,运算符(+-*d),这个d的话是我们定义的一个数,

其中2d3可以这样理解,从1~3中随机选择一个数,执行两次,然后我们得到的最小值是1+1=2,最大值是3+3=6,

就是给你这样一个表达式然后让你求出他的最大值和最小值

PS:其中d的优先级仅次于()

思路:这个题目首先想到了中缀表达式的求值方法,后来发现不怎么会,看了网上大多数的做法发现他们都是用中缀变为后缀,这样就消除了优先级的关系,这样就可以在后面直接计算ma栈和mi栈中的值了,

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
using namespace std;
using namespace std;
typedef long long ll;
struct ob  //为了能把符号和数字都放到一个队列里。。
{
    ll nu;
    char fu;
    ob() {};
    ob(ll x)
    {
        nu = x;
        fu = 0;
    }
    ob(char c)
    {
        nu = 0;
        fu = c;
    }
};
queue<ob>suf;//后缀表达式
stack<char>st;//符号栈
stack<ll>mi, ma;//保存最大值和最小值
string s;
int pri[129];//符号优先级
int main()
{
    pri['('] = 0;
    pri['+'] = pri['-'] = 1;
    pri['*'] = 2;
    pri['d'] = 3;
    pri[')'] = 4;//定义符号优先级
    while (cin >> s)
    {
        while (suf.size())
        {
            suf.pop();
        }
        while (st.size())
        {
            st.pop();
        }
        while (mi.size())
        {
            mi.pop();
        }
        while (ma.size())
        {
            ma.pop();
        }
        ll t = 0;
        int i = 0;
        while (i < s.size())
        {
            if (s[i] >= '0'&&s[i] <= '9')//数字直接入队
            {
                t = 0;
                while (s[i] >= '0'&&s[i] <= '9')
                {
                    t = t * 10 + s[i] - '0';
                    i++;
                }
                suf.push(ob(t));
            }
            else
            {
                if (st.empty())
                {
                    st.push(s[i]);
                }
                else
                {
                    if (s[i] == '(')
                        //左括号直接入栈
                    {
                        st.push(s[i]);
                    }
                    else if (s[i] == ')')
                        //遇到右括号,出栈直到左括号
                    {
                        while (st.top() != '(')
                        {
                            suf.push(ob(st.top()));
                            st.pop();
                        }
                        st.pop();
                    }
                    else if (pri[s[i]] > pri[st.top()])
                        //当前优先级大于栈顶符号,入栈
                        st.push(s[i]);
                    else if (pri[s[i]] < pri[st.top()])
                        //当前优先级小于栈顶符号,出栈直到栈顶比当前符号优先级小,入栈
                    {
                        while (st.size()&&pri[st.top()]>=pri[s[i]])
                        {
                            suf.push(ob(st.top()));
                            st.pop();
                        }
                        st.push(s[i]);
                    }
                    else if (pri[s[i]] == pri[st.top()])
                        //优先级相等,出栈一个,入栈一个
                    {
                        suf.push(ob(st.top()));
                        st.pop();
                        st.push(s[i]);
                    }
                }//出栈就是输出到后缀表达式里
                i++;
            }
        }
        while (st.size())
        {
            suf.push(ob(st.top()));
            st.pop();
        }
        while(suf.size())
        {
            ob op=suf.front();
            suf.pop();
            if(op.fu)
            {
                ll A,B,a,b;
                a=A=B=b=0;
                if(mi.size())a=mi.top(),mi.pop();
                if(mi.size())b=mi.top(),mi.pop();
                if(ma.size())A=ma.top(),ma.pop();
                if(ma.size())B=ma.top(),ma.pop();
                ll res=0;
                if(op.fu=='d')
                {
                    if (a < 1)a = 1;
                    if (A < 1)A = 1;
                    if (b < 0)b = 0;
                    if (B < 0)B = 0;
                    ma.push(max(a*b, max(a*B, max(A*b, A*B))));
                    mi.push(min(b, B));
                }
                else if(op.fu=='*')
                {
                    mi.push(min(a*b,min(A*B,min(a*B,A*b))));
                    ma.push(max(a*b,max(A*B,max(a*B,A*b))));
                }
                else if(op.fu=='+')
                {
                    mi.push(min(a+b,min(A+b,min(a+B,A+B))));
                    ma.push(max(a+b,max(A+b,max(a+B,A+B))));
                }
                else
                {
                    mi.push(min(B - A, min(b - a, min(B - a, b - A))));
                    ma.push(max(b - a, max(B - A, max(B - a, b - A))));
                }
            }
            else
            {
                mi.push(op.nu);
                ma.push(op.nu);
            }
        }
        printf("%lld %lld\n",mi.top(),ma.top());
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值