信息学奥赛一本通(C++版)第三部分 数据结构 第一章 栈

版权声明: https://blog.csdn.net/Lu_Anlai/article/details/80390265

第一章 栈



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

【答案&代码】

  代码如下。

扫描二维码关注公众号,回复: 3431186 查看本文章
#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

猜你喜欢

转载自blog.csdn.net/Lu_Anlai/article/details/80390265