题解 P1175 【表达式的转换】

· · 题解

简单来说就是中缀转后缀再一步步求值的过程, 具体方法见李煜东《算法竞赛进阶指南》P48,49,这上面讲得很清楚。(这的确是一本好书),以下是本蒟蒻的程序

#include<bits/stdc++.h>
int sz(char x){
    return (x>='0'&&x<='9');
}
using namespace std;
int g[110],f[110];//g数组记录上一次计算结果,用于拓展f数组; f数组记录本轮的答案用于输出。 
char z[110]; //z数组用于后缀表达式转化时的输出 
char tr[110];//玄学数组tr 存储第一次的后缀表达式
map<char,int> mm;
int main(){
    mm['^']=3;mm['*']=2;mm['/']=2;mm['+']=1;
    mm['-']=1;mm['(']=mm[')']=-100;//用map保存符号优先级 
    int l,s=0,ss=0,i,ans=0,j,sum=0;
    string st,st1;
    cin>>st1;
    st='0';st+=st1;l=st.size();
    //字符串默认从零开始,所以我们在零号位添个零 
    (个人习惯) 
    //中缀表达式---->后缀表达式 
    for (int i=1;i<=l;i++)
    {   //我是一个只会用if的蒟蒻*1 
        if (sz(st[i])) ss++,cout<<st[i]<<" ",sum++,tr[sum]=st[i];else
        {
            if (st[i]=='(') s++,z[s]=st[i];else     
            //处理左括号 
            if (st[i]==')') 
                {
                    while (z[s]!='(') cout<<z[s]<<" ",sum++,tr[sum]=z[s],s--;
                    s--;            //处理右括号
                }   else
                {                   //处理运算符 
                    while (mm[z[s]]>=mm[st[i]]&&s>=1)   //比较优先级 
                    cout<<z[s]<<" ",sum++,tr[sum]=z[s],s--;
                    s++;z[s]=st[i];
                }
        } 
    }   //用tr记录输出结果 
    cout<<endl;
    //*********************************************
    int big=200000000;
    for (i=1;i<=sum;i++)
    {   //我是一个只会用if的蒟蒻*2
        if (sz(tr[i])) g[i]=int(tr[i])-48;else 
        if (tr[i]=='+') g[i]=big+1;else
        if (tr[i]=='-') g[i]=big+2;else
        if (tr[i]=='*') g[i]=big+3;else
        if (tr[i]=='/') g[i]=big+4;else
        if (tr[i]=='^') g[i]=big+5;
        // 后缀表达式一定不含括号(这就是它优美的原因) 
    }   //将运算符用 200000000+x表示,不太保险,但亲测不会冲突。 
    while (sum>1)//不解释 
    {
        int t=0;//标记 
        f[1]=g[1];f[2]=g[2];//前两位预处理 
        for (i=3;i<=l;i++)
        {
            int x=f[i-1];int y=f[i-2];
            if (g[i]==big+1) ans=x+y,t=1;else   // 加法 
            if (g[i]==big+2) ans=y-x,t=1;else   // 减法 
            if (g[i]==big+3) ans=x*y,t=1;else   // 乘法 
            if (g[i]==big+4) ans=y/x,t=1;else   // 除法 
            if (g[i]==big+5) ans=pow(y,x),t=1;else // 乘方 
            f[i]=g[i];  //  非运算符则照抄 
            if (t==1) break;
        }
        f[i-2]=ans; 
        //f[i-2]与f[i-1]的运算结果覆盖在f[i-2]上 
        for (j=i+1;j<=sum;j++) f[j-2]=g[j]; 
        //将剩下的数照抄下来 
        sum-=2;//一次运算减少一个数和一个运算符 
        for (j=1;j<=sum;j++)
        {   //我是一个只会用if的蒟蒻*3
            if (f[j]==big+1) cout<<"+ ";else
            if (f[j]==big+2) cout<<"- ";else
            if (f[j]==big+3) cout<<"* ";else
            if (f[j]==big+4) cout<<"/ ";else
            if (f[j]==big+5) cout<<"^ ";else
            cout<<f[j]<<" ";
            g[j]=f[j];  
            //记录本轮答案用于下轮拓展 
        }//每轮输出,将 200000000+x转回运算符 
        cout<<endl;
    }
    return 0;
}