0126模拟赛总结

(用自己的笔记本码字整个人都舒适了起来

1、表达式括号匹配

问题描述

假设一个表达式有英文字母(小写)、运算符(+,一,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”,表达式长度小于255,左圆括号少于20个。

输入文件

输入文件stack.in包括一行数据,即表达式,

输出文件

输出文件stack.out包括一行,即“YES”或“NO”。

样例输入

12* (x+y) (1-x)@

样例输出1

YES

样例输入2

(25+x) * (a* (a+b+b) @

样例输出2

NO

洛谷红题,灰常简单。

#include<bits/stdc++.h>
using namespace std;
int a[300],n=0;
bool qwq(){
    int top=0;
    for(int i=0;i<n;i++){
        if(a[i]==1) top++;
        else if(a[i]==2) top--;
        if(top<0) return 0;
    }
    if(top>0) return 0;
    return 1;
}
int main(){
    string s;
    cin>>s;
    int len=s.length();
    for(int i=0;i<len;i++){//似乎没啥必要
        if(s[i]=='(') a[n++]=1;
        else if(s[i]==')') a[n++]=2;
    }
    if(qwq()) cout<<"YES";
    else cout<<"NO";
    return 0;
}

2、括弧匹配检验

问题描述

假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,如([]()或[([][])]等为正确的匹配,[(])或([]()或(()))均为错误的匹配。
现在的问题是,要求检验一个给定表达式中的括弧是否正确匹配?输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出“OK”,不匹配就输出“Wrong”。输入一个字符串:[([][])],输出:OK

输入格式

输入仅一行字符(字符个数小于255)

输出格式

匹配就输出“OK”,不匹配就输出“Wrong”。

输入样例

[ (] )

输出样例

Wrong

随便用个栈存储一下就好啦。

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s,s2;
    cin>>s;
    int len=s.length(),tf=0;
    for(int i=0;i<len;i++){
        if(tf==0){s2[++tf]=s[i];continue;}
        if(s[i]==']'&&s2[tf]=='['){--tf;continue;}
        if(s[i]==')'&&s2[tf]=='('){--tf;continue;}
        if(s[i]=='('||s[i]=='['){s2[++tf]=s[i];continue;}
    }
    if(tf==0) cout<<"OK";
    else cout<<"Wrong";
    //for(int i=0;i<n;i++) cout<<a[i];cout<<endl;
    return 0;
}

3、字符串匹配问题

问题描述

字符串中只含有括号 0. 0..1,判断输入的字符串中括号是否匹配,如果括号有互相包含的形式,从内到外必须是<>,(),[],{}。例如。输入:[()] 输出:YES,而输入([]),([)]都应该输出 NO.

输入格式

文件的第一行为一个整数n. 表示以下有多少个由括好组成的字符串,接下来的n行。每行都是一个由括号组成的长度不超过255的字符串,

输出格式

在输出文件中有n行,每行都是YES或NO.

输入样例

5

{}{}<><>()()[][]

{{}}{{}}<<>><<>>(())(())[[]][[]]

{{}}{{}}<<>><<>>(())(())[[]][[]]

{<>}{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]

><}{{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]

输出样例
YES

YES

YES

YES

NO

好的首先要看题,比如小括号不能包含大括号这件事(悲),当然当我们看见了这个要求之后用打表很容易解决这个问题。

然后就是上一题代码的无脑重复。

#include<bits/stdc++.h>
using namespace std;int main(){
    char s[10086],s2[10086];
    int n,tf;
    cin>>n;for(int o=0;o<n;o++){
        cin>>s;
        int len=strlen(s);tf=0;
        for(int i=0;i<len;i++){
            if(tf==0){s2[++tf]=s[i];continue;}
            if(s[i]==']'&&s2[tf]=='['){--tf;continue;}
            if(s[i]==')'&&s2[tf]=='('){--tf;continue;}
            if(s[i]=='}'&&s2[tf]=='{'){--tf;continue;}
            if(s[i]=='>'&&s2[tf]=='<'){--tf;continue;}
            if(s[i]=='('||s[i]=='['||s[i]=='<'||s[i]=='{'){s2[++tf]=s[i];continue;}
        }
        if(tf!=0){cout<<"NO"<<endl;continue;}
        bool q=1;
        for(int i=0;i<len-1;i++){
            if(s[i]=='}'&&s[i+1]==']'){cout<<"NO"<<endl;q=0;break;}
            if(s[i]=='}'&&s[i+1]==')'){cout<<"NO"<<endl;q=0;break;}
            if(s[i]=='}'&&s[i+1]=='>'){cout<<"NO"<<endl;q=0;break;}
            if(s[i]==']'&&s[i+1]==')'){cout<<"NO"<<endl;q=0;break;}
            if(s[i]==']'&&s[i+1]=='>'){cout<<"NO"<<endl;q=0;break;}
            if(s[i]==')'&&s[i+1]=='>'){cout<<"NO"<<endl;q=0;break;}
            
        }
        if(q) cout<<"YES"<<endl;
    }
    
    //for(int i=0;i<n;i++) cout<<a[i];cout<<endl;
    return 0;
}

4、计算

问题描述

小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“)”,“0-9”,“+”,“-”,“*”,“/”,“^”,求出的值就是密码,小明数学学得不好,还需你帮他的忙。(“/”用整数除法)

输入

输入文件calc.in共1行,为一个算式。

输出

输出文件calc.out共1行,就是密码。

输入样例

1+ (3+2) * (7^2+6*9) (2)

输出样例

258

限制

100%的数据满足:算式长度<=30其中所有数据在2^31的范围内。

两步走战略:中缀转后缀,后缀求值。

一定要转后缀!!!否则智能计算器大概率会成为智障计算器。

第一步:中缀转后缀。

首先定义两个栈s1,s2及各自栈顶指针top1,top2。

从头到尾扫描表达式一次:

1.当遇到数字直接放入s2;

2.当遇到左括号||top1==0||当前运算符优先级大于s1栈顶运算符优先级,直接放入s1;

3.当遇到右括号s1栈顶元素依次出栈存入s2直到遇到左括号,此左括号出栈;

4.当前运算符优先级小于等于s1栈顶运算符优先级,s1栈顶元素依次出栈存入s2直至当前运算符优先级大于等于s1栈顶运算符优先级,当前运算符放入s1;

最后将s1剩余元素从栈顶依次出栈放入s2,我们就成功向ac迈出了伟大的一步。

第二步:后缀求值。

从头到尾扫描s2:

1.遇到数字,将其存入数组a;

2.遇到运算符,对a的后两个元素进行相应计算,数组a长度减一,将结果放入数组末空间。

最后输出数组末元素的值,我们就成功实现了从智障计算器到智能计算器的伟大飞跃,帮助非常不聪明的小明破解了密码。

#include<bits/stdc++.h>
using namespace std;
int check(char x){
    if(x=='+'||x=='-') return 1;
    if(x=='*'||x=='/') return 2;
    if(x=='^') return 3;
    return 0;
}
int ksm(int x,int y){
    int res=1;
    for(;y!=0;y/=2){
        if(y%2==1) res*=x;
        x*=x;
    }
    return res;
}
int main(){
    string s,s1,s2;
    int top1=0,top2=0;
    cin>>s;
    int len=s.length();
    for(int i=0;i<len;i++){
        if(s[i]>='0'&&s[i]<='9') s2[++top2]=s[i];
        else{
            if(s[i]=='('||top1==0||check(s1[top1])<check(s[i])) s1[++top1]=s[i];
            else if(s[i]==')'){for(;s1[top1]!='(';) s2[++top2]=s1[top1--];top1--;}
            else{for(;check(s1[top1])>=check(s[i])&&s[i]!=')';){s2[++top2]=s1[top1--];}s1[++top1]=s[i];}
        }
    }
    for(;top1>=0;top1--){s2[++top2]=s1[top1];}
    //for(int i=1;i<top2;i++) cout<<s2[i]<<" ";
    int a[100],n=0;
    for(int i=1;i<top2;i++){
        if(s2[i]>='0'&&s2[i]<='9') a[++n]=s2[i]-'0';
        else if(s2[i]=='+'){
            n--;a[n]=a[n]+a[n+1];
        }
        else if(s2[i]=='-'){
            n--;a[n]=a[n]-a[n+1];
        }
        else if(s2[i]=='*'){
            n--;a[n]=a[n]*a[n+1];
        }
        else if(s2[i]=='/'){
            n--;a[n]=a[n]/a[n+1];
        }
        else if(s2[i]=='^'){
            n--;a[n]=ksm(a[n],a[n+1]);
        }
    }
    printf("%d",a[n]);
    return 0;
}

(其实快速幂大可不必

5、中缀表达式值

问题描述

输入一个中缀表达式(由0-9组成的运算数、加+减一乘*除/四种运算符、左右小括号组成,注意“一”也可作为负数的标志,表达式以“@”作为结束符),判断表达式是否合法,如果不合法,请输出“NO”;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出、
注意:必须用栈操作,不能直接输出表达式的值。

输入文件

输入文件的第一行为一个以@结束的字符串。

输出文件

如果表达式不合法,请输出“NO”,要求大写。如果表达式合法,请输出计算结果。

输入样例

1+2*8-9

输出样例

8

有了上一道题的基础,这道题就变得非常容易了,只需判断表达式的合法性。

本蒟蒻那些奇奇怪怪的判断:

1.不以“-”或“(”开头,no;

2.括号不匹配,no;

3.出现“++”“+*”等两个连续运算符,no;

4.以运算符结尾,no;

5.左括号和右括号挨着出现,no;

(话说这些事也就小明干得出来)

好的再也想不出来了。

#include<bits/stdc++.h>
using namespace std;
int check(char x){
    if(x=='+'||x=='-') return 1;
    if(x=='*'||x=='/') return 2;
    if(x=='^') return 3;
    return 0;
}
int main(){
    string s,s1,s2;
    cin>>s;
    int q=0,top1=0,top2=0,len=s.length()-1;
    if((s[0]<'0'||s[0]>'9')&&s[0]!='-'&&s[0]!='('){printf("NO");return 0;}
    for(int i=0;i<s.length()-1;i++){
        if(i!=s.length()-2&&(s[i]<'0'||s[i]>'9')&&(s[i+1]<'0'||s[i+1]>'9')&&s[i+1]!='('&&s[i+1]!=')'&&s[i]!='('&&s[i]!=')'){printf("NO");return 0;}
        if(i!=s.length()-2&&s[i]=='('&&s[i+1]==')'){printf("NO");return 0;}
        if(s[i]=='(') q++;
        if(s[i]==')') q--;
        if(q<0){printf("NO");return 0;}
        if(i==s.length()-2&&(s[i]<'0'||s[i]>'9')){printf("NO");return 0;}
    }
    if(q>0){printf("NO");return 0;}
    for(int i=0;i<len;i++){
        if(s[i]>='0'&&s[i]<='9') s2[++top2]=s[i];
        else{
            if(s[i]=='('||top1==0||check(s1[top1])<check(s[i])) s1[++top1]=s[i];
            else if(s[i]==')'){for(;s1[top1]!='(';) s2[++top2]=s1[top1--];top1--;}
            else{for(;check(s1[top1])>=check(s[i])&&s[i]!=')';){s2[++top2]=s1[top1--];}s1[++top1]=s[i];}
        }
    }
    for(;top1>=0;top1--){s2[++top2]=s1[top1];}
    //for(int i=1;i<top2;i++) cout<<s2[i]<<" ";
    int a[100],n=0;
    for(int i=1;i<top2;i++){
        if(s2[i]>='0'&&s2[i]<='9') a[++n]=s2[i]-'0';
        else if(s2[i]=='+'){
            n--;a[n]=a[n]+a[n+1];
        }
        else if(s2[i]=='-'){
            n--;a[n]=a[n]-a[n+1];
        }
        else if(s2[i]=='*'){
            n--;a[n]=a[n]*a[n+1];
        }
        else if(s2[i]=='/'){
            n--;a[n]=a[n]/a[n+1];
        }
    }
    printf("%d",a[n]);
    return 0;
}
posted @ 2022-01-26 23:05  专吃小仙女  阅读(74)  评论(0)    收藏  举报