Codeforces 7E - Defining Macros 题解

目录

  • Codeforces 7E - Defining Macros 题解

    • 前言
    • 做法
    • 程序
    • 结尾

Codeforces 7E - Defining Macros 题解

前言

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

这是一道Codeforces题目

做法

一道大模拟

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

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

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

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

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

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

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

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

  • /要求左侧对象优先级不大于1,右侧对象优先级等于0
  • *要求左侧对象优先级不大于1,右侧对象优先级不大于1
  • -要求右侧对象优先级不大于1
  • 其余对象不做要求

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

  • 空表达式常量变量优先级\(0\),
  • 优先级为内部表达式优先级,合法也取决于内部表达式是否合法
  • (表达式),优先级为\(0\),合法取决于内部是否合法
  • 表达式+表达式表达式-表达式,合法取决于+,-的运算,优先级为\(2\)
  • 表达式/表达式表达式/表达式,合法取决于*,/的运算,优先级为\(1\)

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

程序

#include<bits/stdc++.h>
using namespace std;

int n;
vector<string> expr[105];
//expr为id对应的处理好的表达式序列
int prio[105];
//prio为记忆化处理id对应的表达式的优先级
map<string,int> 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"<<endl;
    return false;
}

int dfs(int id);

inline bool isnumber(const string &s){
//string是否存入数字
    for(int i=0;i<s.size();i++){
        if(s[i]<'0'||s[i]>'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<s.size();i++){
        if(!isalpha(s[i]))return false;
    }return true;
}

int parse(const vector<string> &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: "<<v[l]<<endl;
        //cerr<<"PARSE INVALID"<<endl;
        return -1;//什么都不是,不可能出现这种情况(除非写错了)
    }
    if(v[l]=="("&&v[r-1]==")"){//被括号包裹
        bool f=true;
        int bkc=0;
        for(int i=l;i<r;i++){//检查括号配对情况
            if(v[i]=="(")bkc++;
            if(v[i]==")")bkc--;
            if(bkc==0&&i+1!=r){
                f=false;
                break;
            }
        }
        if(f){
            parse(v,l+1,r-1);
            return 0;
        }
    }
    int bkc=0;
    for(int i=r-1;i>=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"<<endl;
                exit(0);//不合法直接退出
            }
        }
        if(v[i]=="-"){
            if(valid(parse(v,l,i),'-',parse(v,i+1,r))){
                return 2;
            }else{
                cout<<"Suspicious"<<endl;
                exit(0);//不合法直接退出
            }
        }
    }
    for(int i=r-1;i>=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"<<endl;
                exit(0);//不合法直接退出
            }
        }
        if(v[i]=="/"){
            if(valid(parse(v,l,i),'/',parse(v,i+1,r))){
                return 1;
            }else{
                cout<<"Suspicious"<<endl;
                exit(0);//不合法直接退出
            }
        }
    }
    //cerr<<"PARSING: "<<l<<' '<<r<<endl;
    //cerr<<"PARSE INVALID"<<endl;
    return -1;//不可能出现的情况
}

int dfs(int id){//记忆化计算id对应的表达式的优先级
    //cerr<<"DFSING IN: "<<id<<endl;cerr<<prio[id]<<endl;
    if(prio[id]!=-1)return prio[id];
    return prio[id]=parse(expr[id],0,expr[id].size());
}

vector<string> mkexp(const string &s){//处理原始字符串,获得表达式对象的序列
    vector<string> res;
    for(int i=0;i<s.size();i++){
        if(s[i]==' '){
            continue;
        }
        if(s[i]=='('){
            res.push_back("(");
            continue;
        }
        if(s[i]==')'){
            res.push_back(")");
            continue;
        }
        if(s[i]=='+'){
            res.push_back("+");
            continue;
        }
        if(s[i]=='-'){
            res.push_back("-");
            continue;
        }
        if(s[i]=='*'){
            res.push_back("*");
            continue;
        }
        if(s[i]=='/'){
            res.push_back("/");
            continue;
        }
        string tmp;
        int j;
        for(j=i;j<s.size()&&(isalpha(s[j])||(s[j]>='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"<<endl;//由于不合法会退出,这里可以直接输出合法

    return 0;
}

结尾

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

原文地址:https://www.cnblogs.com/BlahDuckling747/p/12026484.html

时间: 2024-11-05 22:43:17

Codeforces 7E - Defining Macros 题解的相关文章

codeforces A. Supercentral Point 题解

One day Vasya painted a Cartesian coordinate system on a piece of paper and marked some set of points(x1,?y1),?(x2,?y2),?...,?(xn,?yn). Let's define neighbors for some fixed point from the given set (x,?y): point (x',?y') is (x,?y)'s right neighbor,

codeforces New Year Present 题解

The New Year is coming! That's why many people today are busy preparing New Year presents. Vasily the Programmer is no exception. Vasily knows that the best present is (no, it's not a contest) money. He's put n empty wallets from left to right in a r

codeforces Sereja and Dima 题解

Sereja and Dima play a game. The rules of the game are very simple. The players have n cards in a row. Each card contains a number, all numbers on the cards are distinct. The players take turns, Sereja moves first. During his turn a player can take o

codeforces D. Ice Sculptures 题解

The Berland University is preparing to celebrate the 256-th anniversary of its founding! A specially appointed Vice Rector for the celebration prepares to decorate the campus. In the center of the campus n ice sculptures were erected. The sculptures

Educational Codeforces Round 64部分题解

Educational Codeforces Round 64部分题解 A 题目大意:给定三角形(高等于低的等腰),正方形,圆,在满足其高,边长,半径最大(保证在上一个图形的内部)的前提下. 判断交点个数是否有限,如果有限,输出. 很明显当正方形套三角形或者三角形套正方形是交点个数是无限的(因为有一条边相交) 其他图形的嵌套交点个数比较好判断,不多赘述 但是注意坑点: 当按照矩形,园,三角这样的顺序是,三角与圆的一个交点是与圆和正方形的交点重合的,判一下就好了 #include<cstdio>

Codeforces Round #616 部分题解

老年选手诈尸? A,B 咕了. C - Prefix Enlightenment 很容易看出这个限制条件可以推出每个点最多被两个集合包含.按照套路,很容易联想到给这两个集合连一条边,表示他们的状态要相同/不同. 因为保证了有解,所以从左往右扫的时候拿并查集维护一下每个连通块的二分图情况,选较小的那一边. 如果只被一个集合覆盖,那么就相当于强制这个集合选/不选,在做并查集的时候特判一下即可. 代码咕了. D - Coffee Varieties (hard version) 作为一名憨憨,做法当然

【codeforces】【比赛题解】#854 CF Round #433 (Div.2)

cf一如既往挺丧 看丧题点我! [A]分数 Petya是数学迷,特别是有关于分数的数学.最近他学了所谓一个分数被叫做"真分数"当且仅当其分子小于分母,而一个分数被叫做"最简分数"当且仅当其分子分母互质.在闲暇时间,Petya在用计算器研究:如何把最简真分数转换为小数等问题.有一天他不小心把除号(÷)按成了加号(+),导致他得到了分子与分母的和.Petya想要得到他原来的分数,但他很快发现这不是唯一的.所以现在他想要知道最大的最简真分数使得其分子与分母的和为n. 输入

Codeforces #Round 376 部分题解

A: 题目传送门:http://codeforces.com/problemset/problem/731/A 直接根据题意模拟即可 1 #include "bits/stdc++.h" 2 3 using namespace std ; 4 typedef long long QAQ ; 5 6 char s[ 1010 ] ; 7 8 inline int Calc ( const char x , const char y ) { 9 if ( x > y ) return

Codeforces A. Double Cola 题解

题目很奇怪,就是5个人排队喝可乐,喝完之后编程两个人,然后拍在队后面,然后继续喝可乐. 给出个数值,代表第几罐可乐,问会是第几个人喝到? http://codeforces.com/problemset/problem/82/A 一个数学问题,仔细点就好了. 要熟练的知识点: 1 要熟悉解决这种递增数列,如何减去循环部分 2 要知道如何计算,求余取答案 #include <string> #include <iostream> using namespace std; void D