20200404栈和队列训练总结

1.车厢调度(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
【提示】解析:观察发现,整个调度过程其实是在模拟入栈出栈的过程,而这个过程中,我们可以分成三种状态:栈前、栈中、栈后。我们可以发现,当某个数字出栈了,说明比它小的数字要么已经出栈了,要么还在栈里,不能是入栈前状态,并且在栈中的顺序是从大到小的(从栈顶往栈底看),比如出5,那么1,2,3,4要么已经在5之前出了,要么还在栈中(假如1,3,4在栈中,从栈顶往栈底看依次为4,3,1),不能是入栈前的状态。如果某个数字要出栈,那么当前在栈中的数字都必须小于它,否则就与栈的性质矛盾,不合法,于是我们可以这样解决:
从第一个数字开始扫描,a[i]表示当前出栈的数字,如果有比a[i]大的数字还在栈中,那么就产生矛盾,输出“NO”;否则,标记当前数字a[i]为栈后状态,那么[1, a[i]-1]这些数字如果还没出栈,标记为栈中状态。具体我们可以用0表示为确定状态,1表示栈中状态,2表示栈后状态。
运行错误代码

#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
int a[1005],n;
stack<int>S;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int k=1;
    for(int i=1;i<=n;i++)
    {
        S.push(i);
        while(S.top()==a[k]&&(!S.empty()))
        {
            S.pop();
            k++;
        }
    }
    if(S.empty())
        cout<<"YES";
    else cout<<"NO";
    return 0;
}

只要把while判断条件里的二者调换位置,即先判断是否非空,若非空再判断其他条件,即可AC
AC代码

#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
int a[1005],n;
stack<int>S;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int k=1;
    for(int i=1;i<=n;i++)
    {
        S.push(i);
        while((!S.empty())&&S.top()==a[k])
        {
            S.pop();
            k++;
        }
    }
    if(S.empty())
        cout<<"YES";
    else cout<<"NO";
    return 0;
}

2.1331:【例1-2】后缀表达式的值
【题目描述】
从键盘读入一个后缀表达式(字符串),只含有0-9组成的运算数及加(+)、减(—)、乘()、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要判断给你的表达式是否合法。以@作为结束标志。
比如,16–9
(4+3)转换成后缀表达式为:16□9□4□3□+*–,在字符数组A中的形式为:
在这里插入图片描述
栈中的变化情况:
在这里插入图片描述
运行结果:-47
提示:输入字符串长度小于250,参与运算的整数及结果之绝对值均在264264范围内,如有除法保证能整除。

【输入】
一个后缀表达式。
【输出】
一个后缀表达式的值。
【输入样例】
16 9 4 3 +*-@
【输出样例】
-47

#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
int a[1005],n;
stack<int>S;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int k=1;
    for(int i=1;i<=n;i++)
    {
        S.push(i);
        while((!S.empty())&&S.top()==a[k])
        {
            S.pop();
            k++;
        }
    }
    if(S.empty())
        cout<<"YES";
    else cout<<"NO";
    return 0;
}

3.1332:【例2-1】周末舞会
【题目描述】
假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴。规定每个舞曲能有一对跳舞者。若两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。现要求写一个程序,模拟上述舞伴配对问题。

【输入】
第一行两队的人数;
第二行舞曲的数目。
【输出】
配对情况。
【输入样例】
4 6
7
【输出样例】
1 1
2 2
3 3
4 4
1 5
2 6
3 1

#include<iostream>
#include<queue>
using namespace std;
queue<int>Q1,Q2;
int main()
{
    int m,n,k;
    cin>>m>>n>>k;
    for(int i=1;i<=m;i++) Q1.push(i);
    for(int i=1;i<=n;i++) Q2.push(i);
    while(k--)
    {
        cout<<Q1.front()<<" "<<Q2.front()<<endl;
        Q1.push(Q1.front());
        Q2.push(Q2.front());
        Q1.pop();
        Q2.pop();
    }
    return 0;
}

4.1335:【例2-4】连通块
【题目描述】
一个n * m的方格图,一些格子被涂成了黑色,在方格图中被标为1,白色格子标为0。问有多少个四连通的黑色格子连通块。四连通的黑色格子连通块指的是一片由黑色格子组成的区域,其中的每个黑色格子能通过四连通的走法(上下左右),只走黑色格子,到达该联通块中的其它黑色格子。

【输入】
第一行两个整数n,m(1≤n,m≤100),表示一个n * m的方格图。
接下来n行,每行m个整数,分别为0或1,表示这个格子是黑色还是白色。
【输出】
一行一个整数ans,表示图中有ans个黑色格子连通块。
【输入样例】
3 3
1 1 1
0 1 0
1 0 1

【输出样例】
3

#include<iostream>
using namespace std;
const int N=110;
const int flag[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int a[N][N],queue[N*N][2];
int n,m,ans;
bool p[N][N];
void bfs(int x,int y)
{
    int front=0,rear=2;
    queue[1][0]=x,queue[1][1]=y;
    while(front<rear-1)
    {
        ++front;
        x=queue[front][0];
        y=queue[front][1];
        for(int i=0;i<4;i++)
        {
            int x1=x+flag[i][0];
            int y1=y+flag[i][1];
            if(x1<1||y1<1||x1>n||y1>m||!a[x1][y1]||p[x1][y1]) continue;
            p[x1][y1]=true;
            queue[rear][0]=x1;
            queue[rear++][1]=y1;
        }
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>a[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(a[i][j]&&!p[i][j])
        {
            ++ans;
            bfs(i,j);
        }
    cout<<ans<<endl;
    return 0;
}
原创文章 25 获赞 38 访问量 846

猜你喜欢

转载自blog.csdn.net/weixin_46434074/article/details/105315456