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
{}{}<><>()()[][]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{<>}{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]
><}{{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]
输出样例
YESYES
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; }
浙公网安备 33010602011771号