• POJ 2792 Brackets Removal


    题意:给定一个表达式,去除所有能去掉的括号

    分析:因为是表达式,所以想套用LR(1)分析法和分解表达式,一步一步手动模拟去括号,结果总是拆东墙补西墙,搞不出来。

    三天后看解题报告,标程是通过加括号来解决的,构造一颗二叉树,去掉所有括号,叶子是变量,非叶子其他的节点是运算符,节点的深度和他所在的括号数相同,

    由于*和/的计算优先级比加和减高,所以当非叶子节点的运算符的优先级比孩子节点的高时,必须通过加括号来维护

    pascal的标程是错(虽然它的文件名已经含有bug的单词,但是错的怎么能放到标程里!),有两处错误,我都发现过,可都只改了一处来测试,耗了一个下午,

    看到java版的编程才恍然大悟,不自信啊!

    第一处:由于同深度同优先级的时候是从左往右计算的,而它却写成从右往左。

    第二处:1,在当非叶子节点的运算符的优先级比孩子节点的高,要加括号时,取反运算符不(false)应该影响括号内,它是沿用父节点的inverse;

        2,而在同深度同优先级的时候,应该沿用父节点的inverse,它却是不影响(false);

    #include<cstdio>
    #define MAXN 1010
    using namespace std;
    
    struct ops
    {
        int l,r,pr;
        char op;
    };
    
    ops o[MAXN];
    char s[MAXN];
    int k,p;
    int expr();
    
    int createOps(int l,int r,char op,int pr)
    {
        k++;
        o[k].l=l;
        o[k].r=r;
        o[k].pr=pr;
        o[k].op=op;
        return k;
    }
    
    int factor()
    {
        int ret;
        if(s[p]>='a'&&s[p]<='z')
            ret=createOps(0,0,s[p++],3);
        else
        {
            p++;
            ret=expr();
            p++;
        }
        return ret;
    }
    
    int term()
    {
        int l,r,ret;
        char op;
        l=factor();
        while(s[p]=='*'||s[p]=='/')
        {
            op=s[p++];
            r=factor();
            l=createOps(l,r,op,2);
        }
        return l;
    }
    
    int expr()
    {
        int l,r;
        char op;
        l=term();
        while(s[p]=='+'||s[p]=='-')//第一处,原为 if
        {
            op=s[p++];
            r=term(); //第一处,原为 r=expr();
            l=createOps(l,r,op,1);
        }
        return l;
    }
    
    void Print(int n,bool inverse)
    {
        int l,r;
        if(o[n].op>='a'&&o[n].op<='z')
        {
            putchar(o[n].op);
            return;
        }
        l=o[n].l;
        r=o[n].r;
        if(o[l].pr>o[n].pr)
            Print(l,false);
        else if(o[l].pr<o[n].pr)
        {
            putchar('(');
            Print(l,false);//第二处的第一点 ,原为 Print(l,inverse);
            putchar(')');
        }
        else
            Print(l,inverse);//第二处的第二点  ,原为 Print(l,false);
            
        if(!inverse)
            putchar(o[n].op);
        else if(o[n].op=='+')
            putchar('-');
        else if(o[n].op=='-')
            putchar('+');
        else if(o[n].op=='*')
            putchar('/');
        else
            putchar('*');
        
        if(o[r].pr>o[n].pr)
            Print(r,false);
        else if(o[r].pr<o[n].pr)
        {
            putchar('(');
            Print(r,false);
            putchar(')');
        }
        else//如果不改第一处的话,错误就会在这里产生 
        {
            if(o[n].op=='-'||o[n].op=='/')
                inverse=!inverse;
            Print(r,inverse);
        }
    }
    
    int main()
    {
        gets(s);
        k=p=0;
        int n=expr();
        Print(n,false);
        return 0;    
    }
  • 相关阅读:
    Service解析
    Android消息处理
    FragmentTransaction.addToBackStack无效的问题
    Activity生命周期
    width 的100% 与 auto
    parseInt 与 parseFloat 解析
    splice
    <c:forEach>
    笔记,遮罩。。
    nginx 的windows 基本配置
  • 原文地址:https://www.cnblogs.com/xchaos/p/2532163.html
Copyright © 2020-2023  润新知