Defining Macros CodeForces - 7E

其实也不算原创,综合了一下网上神牛题解的思路与实现技巧。

先说题意:

给你一些宏定义,判断最后的式子是否能正确表达原来的意思
这是一个表达式求解的题
不正确表达无非就是前后两个符号会通过 改变运算顺序而错误表达原来的意思
如 a- (B+C) 无括号就会表达错误 
首先可以给表达式分类,来简化我们的判断
1.无论如何都是正确的
一个纯单词或括号非错式子
2.错误的
3.在前面加上 “-” ,或挨着“*” “/”就会错的(如"a+b")
4.在前面加上“/” ,就会错的 ,挨着“*”或“-”不会错(如“a/b““a*b”)
只有这四种
那么每次以一个运算符c为中心,若可以将表达式s分成左右两块独立的表达式a和b:
如果a或b是错的,s也是错的,为2。
否则:
如果c为“+”,那么s为3。

如果c为“-”,b为3时s为2,否则为3。
。。。。。。
这样。

可这个程序如何实现呢?
我们用三个参数
s,l,r
分别表示表达式,目前正在计算的左端点,右端点。
返回值为(s,l,r)是哪一类
目标,算出s,0,len(s)-1是哪一类

1.先说最简单的,一个纯单词,先看他有没有define的意义,有就递归去搜,否则 (s,l,r)=1

2.s是由括号括起来的时,(s,l,r)=(s,l+1,r-1);

3.s中有四则运算,找出最后一个使用的运算符(有+-就是+-,否则是*/)

因为最后一个运算符运算时前面的运算都用过了,那么这个运算双方就为前面和后面,

直接分成两半递归调用。

否则,如a/b*c

最后一个为*

如果先分析/,无法找出除数究竟是b还是b*c(要找的话会复杂)

但如果先分析*,一定是c和a/b。

+-也如此

那么程序设计的思路就很清晰了

先特判1.2

再找最后一个计算的运算符(有+-就是+-,否则是*/)

再以运算符为中心分成两半递归处理,四种状态互相转移

思路清晰,码代码就快:

另外,输入很恶心,多看几个题解吧

AC代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<map>
#include<string>
#include<iostream>
#define maxn 105
using namespace std;
int n;
map<string,int>M,F;


char s[maxn],c[maxn][maxn],tmp[maxn],na[maxn][maxn],st[maxn];
int cnt[maxn],len[maxn];

int ser(string s,int l,int r){
	int op=0,kuo=0,a,b;
	string ss;
	for(int i=r;i>=l;i--){
		if(s[i]=='(')
			kuo++;
		if(s[i]==')')
			kuo--;
		if((s[i]=='*' || s[i]=='/') && kuo==0 && op==0) op=i;
		if((s[i]=='+' || s[i]=='-') && kuo==0){
			a=ser(s,l,i-1);
			b=ser(s,i+1,r);
			if(a==2 || b==2) return 2;
			if(s[i]=='+') return 3;
			if(s[i]=='-')
			{
				if(b==3) return 2;
				return 3;
			}
		}
	}
	if(op){
		a=ser(s,l,op-1);
		b=ser(s,op+1,r);
		if(a==2 || b==2) return 2;
		if(s[op]=='*'){
			if(a==3 || b==3) return 2;
			return 4;
		}
		else{
			if(b==3 || b==4 || a==3) return 2;
			return 4;
		}
	}
	if(s[r]==')' && s[l]=='('){
		if(ser(s,l+1,r-1)==2) return 2;
		return 1;
	}
	else{
		ss="";
		for(int i=l;i<=r;i++)
		 	ss+=s[i];
		if(M[ss]) return M[ss];
		return 1;
	}
}

int main(){
	char ANS[2][15]={"OK","Suspicious"};
    string s2,s,s3;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>s;
		cin>>s;
        if(s=="define")cin>>s;
        getline(cin,s2);
        s3="";
        for(int j=0;j<s2.length();j++)
            if(s2[j]!=' ')
                s3+=s2[j];
        M[s]=ser(s3,0,s3.length()-1);
    }
    getline(cin,s2);
    s3="";
    for(int j=0;j<s2.length();j++)
        if(s2[j]!=' ')
            s3+=s2[j];
	printf("%s\n",ANS[ser(s3,0,s3.length()-1)==2]);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值