Codeforces 7E - Defining Macros 题解

[TOC]

Codeforces 7E - Defining Macros 题解

前言

开始使用博客园了,很想写点东西。(逃

这是一道Codeforces题目。

做法

一道大模拟

相信大家都看得懂题目意思,我就不赘述了。

首先我们读进来$n$行,对于每一行,我们把它初步分成一下四块内容:

  • #
  • define
  • 宏的名字
  • 宏的表达式

注意:#define中间可能会有空格,define和宏的名字,宏的名字和宏的表达式之间一定会有空格。

现在我们来处理一下表达式,把它处理到一个序列内,这个序列包含:(,),+,-,*,/,变量,常量

对于每一个对象,我们可以如下定义:(优先级值越小越优先)

  • 变量,常量,括号:优先级为$0$
  • /,*:优先级为$1$
  • +,-:优先级为$2$
  • 宏:优先级为内部表达式的优先级

同时我们可以发现一个表达式,合法时满足以下条件:

  • /要求左侧对象优先级不大于1,右侧对象优先级等于0

  • *要求左侧对象优先级不大于1,右侧对象优先级不大于1

  • -要求右侧对象优先级不大于1

  • 其余对象不做要求

于是,对于一个表达式$S$,我们可以递归地考虑:

  • 空表达式常量变量优先级$0$,

  • 优先级为内部表达式优先级,合法也取决于内部表达式是否合法

  • (表达式),优先级为$0$,合法取决于内部是否合法

  • 表达式+表达式表达式-表达式,合法取决于+,-的运算,优先级为$2$

  • 表达式/表达式表达式/表达式,合法取决于*,/的运算,优先级为$1$

好了,成了,可以写代码了!

程序

#include
using namespace std;

int n;
vector expr[105];
//expr为id对应的处理好的表达式序列
int prio[105];
//prio为记忆化处理id对应的表达式的优先级
map def;
//def为宏名称对应的id

inline bool valid(int lp,char op,int rp){
//左表达式优先级lp,运算符op,右表达式优先级rp,是否合法
    if(op=='/')return lp<=1&&rp<=0;
    if(op=='*')return lp<=1&&rp<=1;
    if(op=='+')return lp<=2&&rp<=2;
    if(op=='-')return lp<=2&&rp<=1;
    //cerr<<"OP INVALID"<'9')return false;
    }return true;
}

inline bool ismacro(const string &s){
//string是否存入宏
    return def.find(s)!=def.end();
}

inline bool isvalue(const string &s){
//string是否存入变量
    for(int i=0;i &v,int l,int r){
    if(l>=r)return 0;//空表达式
    if(l+1==r){//只有一个单独对象
        if(isnumber(v[l])){//是常量
            return 0;
        }
        if(ismacro(v[l])){//是宏
            return dfs(def[v[l]]);
        }
        if(isvalue(v[l])){//是变量,要在宏后判断
            return 0;
        }
        //cerr<<"PARSING: "<=l;i--){//优先找+、-,此处i从小到大亦可
        if(v[i]==")")bkc++;
        if(v[i]=="(")bkc--;
        if(bkc)continue;//判断是否在括号内
        if(v[i]=="+"){
            if(valid(parse(v,l,i),'+',parse(v,i+1,r))){
                return 2;
            }else{
                cout<<"Suspicious"<=l;i--){//再找*、/,此处i从小到大亦可
        if(v[i]==")")bkc++;
        if(v[i]=="(")bkc--;
        if(bkc)continue;//判断是否在括号内
        if(v[i]=="*"){
            if(valid(parse(v,l,i),'*',parse(v,i+1,r))){
                return 1;
            }else{
                cout<<"Suspicious"< mkexp(const string &s){//处理原始字符串,获得表达式对象的序列
    vector res;
    for(int i=0;i='0'&&s[j]<='9'));j++){
            tmp+=s[j];
        }
        res.push_back(tmp);
        i=j-1;//常量,宏,变量都可以按照这个方式处理
    }
    return res;
}

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n;
    {
        string s,t;char c;
        getline(cin,s);
        for(int i=1;i<=n;i++){
            cin>>c>>s>>s;
            //特判#号和define分开的情况
            def[s]=i;
            getline(cin,t);
            expr[i]=mkexp(t);
        }
        getline(cin,t);
        expr[0]=mkexp(t);
    }
    memset(prio,-1,sizeof(prio));
    dfs(0);
    cout<<"OK"<

结尾

祝你们一次AC!虽然人家是写挂好多次的说。。。再看,再看就诅咒你也写挂!哼~

你可能感兴趣的:(Codeforces 7E - Defining Macros 题解)