第一章 栈
T1331 : 后缀表达式的值
【题目描述】
从键盘读入一个后缀表达式(字符串),只含有0-9组成的运算数及加(+)、减(—)、乘(*)、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要判断给你的表达式是否合法。以@作为结束标志。
比如,16–9*(4+3)转换成后缀表达式为:16□9□4□3□+*–,在字符数组A中的形式为:
栈中的变化情况:
运行结果:-47
提示:输入字符串长度小于250,参与运算的整数及结果之绝对值均在264范围内,如有除法保证能整除。
【输入】
一个后缀表达式。
【输出】
一个后缀表达式的值。
【输入样例】
16 9 4 3 +*-@
【输出样例】
-47
【答案&代码】
代码如下。
#include<stdio.h>
#include<string.h>
int main(void){
char str[500];
gets(str);
//printf("%s",str);
long long top=0,stack[500]={0};
for(int i=0,len=strlen(str)-1;i<len;i++)
switch(str[i]){
case '+':stack[--top]+=stack[top+1];break;
case '-':stack[--top]-=stack[top+1];break;
case '*':stack[--top]*=stack[top+1];break;
case '/':stack[--top]/=stack[top+1];break;
case '@':i=len;break;
default:
long long temp=0;
while(str[i]!=' ')
temp=temp*10+str[i]-'0',i++;
stack[++top]=temp;
break;
}
printf("%lld",stack[top]);
return 0;
}
T1353 : 表达式括号匹配(stack)
【题目描述】
假设一个表达式有英文字母(小写)、运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”。表达式长度小于255,左圆括号少于20个。
【输入】
一行数据,即表达式。
【输出】
一行,即“YES” 或“NO”。
【输入样例】
2*(x+y)/(1-x)@
【输出样例】
YES
【答案&代码】
代码如下。
#include<stdio.h>
int main(void){
int n=0;
char temp;
do{
scanf("%c",&temp);
if(temp=='(')
n++;
if(n>0&&temp==')')
n--;
else if(n==0&&temp==')'){
n=-1;
break;
}
}while(temp!='@');
if(n==0)
printf("YES");
else
printf("NO");
return 0;
}
T1354 : 括弧匹配检验
【题目描述】
假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,如([ ]())或[([ ][ ])]等为正确的匹配,[( ])或([ ]( )或 ( ( ) ) )均为错误的匹配。
现在的问题是,要求检验一个给定表达式中的括弧是否正确匹配?
输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出 “OK” ,不匹配就输出“Wrong”。输入一个字符串:[([][])],输出:OK。
【输入】
输入仅一行字符(字符个数小于255)。
【输出】
匹配就输出 “OK” ,不匹配就输出“Wrong”。
【输入样例】
[(])
【输出样例】
Wrong
【答案&代码】
代码如下。
#include<stdio.h>
#include<string.h>
#include<stack>
using std::stack;
stack<char> S;
int main(void){
char str[256];
gets(str);
bool flag=true;
for(int i=0,len=strlen(str);i<len;i++){
if(str[i]=='('||str[i]=='[')
S.push(str[i]);
if(str[i]==')'||str[i]==']'){
if(S.empty()){
flag=false;
break;
}
else if(str[i]==')'&&S.top()=='['){
flag=false;
break;
}
else if(str[i]==']'&&S.top()=='('){
flag=false;
break;
}
else
S.pop();
}
}
if(!S.empty())
flag=false;
if(flag)
printf("OK");
else
printf("Wrong");
return 0;
}
/*
stack<elemType> S;//建立一个元素类型为elemType的栈S
S.push(elem1);//将元素elem1压入栈
elem2=S.pop();//弹出并返回栈顶元素
elem3=S.top();//返回栈顶元素的引用(而不弹出)
S.empty(); //判断栈是否为空,返回布尔类型值
S.clear();//清空栈
*/
T1355 : 字符串匹配问题(strs)
【题目描述】
字符串中只含有括号 (),[],<>,{},判断输入的字符串中括号是否匹配。如果括号有互相包含的形式,从内到外必须是<>,(),[],{},例如。输入: [()] 输出:YES,而输入([]),([)]都应该输出NO。
【输入】
第一行为一个整数n,表示以下有多少个由括好组成的字符串。接下来的n行,每行都是一个由括号组成的长度不超过255的字符串。
【输出】
在输出文件中有n行,每行都是YES或NO。
【输入样例】
5
{}{}<><>()()[][]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{<>}{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]
><}{{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]
【输出样例】
YES
YES
YES
YES
NO
【答案&代码】
代码如下。
#include <stdio.h>
#include <string.h>
char a[]={'{','[','(','<','}',']',')','>'},s[300];
int b[300],stack[300],top;//b[i]与s[i]一一映射
int main(void){
int t,len,i,j,k,flag;//flag合法,非法标记
scanf("%d",&t);
while(t--){
flag=1,top=0;//漏了top=0这句,查了好久
scanf("%s",s);//此处写成 scanf("%d",s); 尽出昏招
len=strlen(s);
for(i=0;i<len;i++)//建立字符与数字的一一映射关系
for(j=0;j<8;j++)
if(s[i]==a[j]){
b[i]=j;
break;
}
i=0;
while(i<len){//是否匹配处理
//printf("b[%d]=%d\n",i,b[i]);
if(b[i]<=3)//b[i]元素想要入栈
if(top==0||b[i]>=stack[top]){//b[i]元素可以入栈,top==0栈为空,或栈内符号满足嵌套关系
top++,stack[top]=b[i];
}else{//b[i]元素无法入栈,该组数据非法,结束该组数据处理
flag=0;
break;
}
else if(b[i]>=4){//b[i]元素希望与栈内元素配对
if(top>0&&stack[top]+4==b[i]){//首先栈内要有元素,同时判断是否配对
top--;
}else{//无法配对,结束 该组数据处理
flag=0;
break;
}
}
i++;
}
if(top)printf("NO\n");//栈内有元素,匹配不成功
else if(flag==1)printf("YES\n");//栈内无元素,匹配成功
else printf("NO\n");//栈内无元素,匹配不成功
}
return 0;
}
T1356 : 计算(calc)
【题目描述】
小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“)”,“0-9”,“+”,“-”,“*”,“/”,“^”,求出的值就是密码。小明数学学得不好,还需你帮他的忙。(“/”用整数除法)
【输入】
共1行,为一个算式。
【输出】
共1行,就是密码。
【输入样例】
1+(3+2)*(7^2+6*9)/(2)
【输出样例】
258
【答案&代码】
代码如下。
#include <stdio.h>
#include <math.h>
int a[2000],n=0,i=0,m=0;
char s[2000],b[2000],c[300];
void compute(){
switch(b[m-1]){//自左往右计算
case '+':a[n-1]+=a[n];break;
case '-':a[n-1]-=a[n];break;
case '*':a[n-1]*=a[n];break;
case '/':a[n-1]/=a[n];break;
case '^':a[n-1]=pow(a[n-1],a[n]);break;
}
b[m-1]=b[m],m--,n--;
}
int can(void){
if(c[b[m-1]]==4||c[b[m]]==4)return 0;
if(c[b[m-1]]>=c[b[m]])return 1;
return 0;
}
int getint(void){//获得整数
int ans=0;
if(s[i+1]=='('){//遇到'('的处理
b[++m]=s[++i];//将'('存入 运算符栈
return getint();//递归调用
}
while('0'<=s[++i]&&s[i]<='9')ans=ans*10+s[i]-'0';
return ans;
}
int main(void){
c['+']=c['-']=1,c['*']=c['/']=2,c['^']=3,c['(']=c[')']=4;
scanf("%s",s+1);
a[++n]=getint();
while(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'||s[i]=='^'||s[i]==')'){
b[++m]=s[i];
if(s[i]==')'){//右括号要单独处理
while(b[m-1]!='(')compute();
m-=2,i++;
continue;
}
while(m>1&&can())compute();
a[++n]=getint();
}
m++;//必须空算一次
while(m>1)compute();
printf("%d",a[1]);
return 0;
}
T1357 : 车厢调度(train)
【题目描述】
有一个火车站,铁路如图所示,每辆火车从A驶入,再从B方向驶出,同时它的车厢可以重新组合。假设从A方向驶来的火车有n节(n≤1000),分别按照顺序编号为1,2,3,…,n。假定在进入车站前,每节车厢之间都不是连着的,并且它们可以自行移动到B处的铁轨上。另外假定车站C可以停放任意多节车厢。但是一旦进入车站C,它就不能再回到A方向的铁轨上了,并且一旦当它进入B方向的铁轨,它就不能再回到车站C。
负责车厢调度的工作人员需要知道能否使它以a1,a2,…,an的顺序从B方向驶出,请来判断能否得到指定的车厢顺序。
【输入】
第一行为一个整数n,其中n≤1000,表示有n节车厢,第二行为n个数字,表示指定的车厢顺序。
【输出】
如果可以得到指定的车厢顺序,则输出一个字符串”YES”,否则输出”NO”(注意要大写,不包含引号)。
【输入样例】
5
5 4 3 2 1
【输出样例】
YES
【答案&代码】
代码如下。
#include<stdio.h>
const int maxn=1000 + 10;
int target[maxn],stack[maxn];
int main(void) {
int n;
scanf("%d",&n);
int target[n+1];
for(int i=1;i<=n;i++)
scanf("%d",&target[i]);
bool flag=true;
int top=0,A=1,B=1;
while(B<=n)
if(A==target[B])
A++,B++;
else if(top&&stack[top]==target[B])
top--,B++;
else if(A<=n)
stack[++top]=A++;
else{
flag=false;
break;
}
if(flag)
printf("YES");
else
printf("NO");
return 0;
}
T1358 : 中缀表达式值(expr)
【题目描述】
输入一个中缀表达式(由0-9组成的运算数、加+减—乘*除/四种运算符、左右小括号组成。注意“—”也可作为负数的标志,表达式以“@”作为结束符),判断表达式是否合法,如果不合法,请输出“NO”;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出。
注意:必须用栈操作,不能直接输出表达式的值。
【输入】
一行为一个以@结束的字符串。
【输出】
如果表达式不合法,请输出“NO”,要求大写。
如果表达式合法,请输出计算结果。
【输入样例】
1+2*8-9
【输出样例】
8
【答案&代码】
代码如下。
404 NOT FOUND