训练内容:
信息学奥赛一本通:栈和队列
本周训练总结:
栈和队列之前刚学的时候就有做过几个题,当然都是超级简单的没有啥思维含量的。本次专门训练栈和队列的题就有点难度了。这里简单总结一下栈和队列的知识点,再整理几个例题。
首先栈和队列都是特殊的线性表。
栈是限定只能在一端进行插入和删除的线性表。也就是先入后出
栈的基本用法:
头文件:#include< stack >
stack< int>p;
p.empty()栈为空则返回真;
p.pop()移除栈顶元素;
p.push()在栈顶添加元素;
p.size()返回栈中元素数目;
p.top()返回栈顶元素;
stack的实现很简单,只需要将底层结构进行约束就可以了。
由于stack后进先出的规则,所以并无走访功能,且stack是没有迭代器的。
队列是限定在一端进行插入,另一端进行删除的线性表。也就是先入先出
队列的基本用法:
头文件:#include< queue>
queue< int >q;
q.back()返回最后一个元素;
q.empty()如果队列为空则返回真;
q.front();返回第一个元素;
q.pop()删除第一个元素;
q.push()在末尾加入一个元素;
q.size()返回队列中元素的个数;
队列符合先进先出后进后出的规则;
内部默认数据存放容器为deque,若要用非默认容器初始化,必须要在模板中指定容器类型。
1355:字符串匹配问题(strs)
下面附上第一次提交的代码
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string s;
s.clear();
stack<int>p;
cin>>s;
int n=s.size();
for(int i=0; i<n; i++)
{
if(s[i]=='(')
p.push(1);
else if(s[i]=='[')
p.push(2);
else if(s[i]=='{')
p.push(3);
else if(s[i]=='<')
p.push(4);
else if(p.empty()==0)
{
if(s[i]==')'&&p.top()==1)
p.pop();
else if(s[i]==']'&&p.top()==2)
p.pop();
else if(s[i]=='}'&&p.top()==3)
p.pop();
else if(s[i]=='>'&&p.top()==4)
p.pop();
else
{
cout<<"NO"<<endl;
return 0;
}
}
else
{
cout<<"NO"<<endl;
return 0;
}
}
if(p.empty()==0)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
}
首先这是一个错误的代码,只能通过几个样例,问题就出在我乱用return上,return是终止函数的恰好样例是最后一个错了所以样例是对的,我又考虑用了break加判断条件但样例总出问题,最后还是回到最原始的一个一个判断,最后进行输出yes or no。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
bool flag=true;
string s;
s.clear();
cin>>s;
stack<char>Q;
while(!Q.empty())
{
Q.pop();
}
for(int i=0;s[i];i++){
if(s[i]=='<'){
Q.push(s[i]);
}
else if(s[i]=='(')
{
if(!Q.empty())
{
if(Q.top()=='<')
flag=false;
else Q.push(s[i]);
}
else Q.push(s[i]);
}
else if(s[i]=='[')
{
if(!Q.empty())
{
if(Q.top()=='('||Q.top()=='<')
{
flag=false;
}
else Q.push(s[i]);
}
else Q.push(s[i]);
}
else if(s[i]=='{')
{
if(!Q.empty())
{
if(Q.top()=='['||Q.top()=='('||Q.top()=='<')
{
flag=false;
}
else Q.push(s[i]);
}
else Q.push(s[i]);
}
else if(s[i]=='>')
{
if(Q.empty())
{
flag=false;
}
else
{
if(Q.top()=='<') Q.pop();
else flag=false;
}
}
else if(s[i]==')')
{
if(Q.empty()) flag=false;
else
{
if(Q.top()=='(') Q.pop();
else flag=false;
}
}
else if(s[i]==']')
{
if(Q.empty()) flag=false;
else
{
if(Q.top()=='[') Q.pop();
else flag=false;
}
}
else if(s[i]=='}')
{
if(Q.empty()) flag=false;
else
{
if(Q.top()=='{') Q.pop();
else flag=false;
}
}
}
if(Q.empty()&&flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
1360:奇怪的电梯(lift)
这是一个bfs的题,之前训练有训练过这部分,
这道题大概意思是有一个电梯,有n层,第i层有一个数a[i],可以到达(i-a[i])层或者(i+a[i])层,你在a层要到b层,问最快需要按几次电梯。从起点开始,往上和往下两个方向搜,不是b层则两个结果压入队列,每次step都要加1,再从队列中取一个往上往下搜,如果重复就剪枝,直到搜到b层返回记录的step或者队列为空返回-1。
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int x;
int step;
};
queue<node> que;
int aa[205];
int vv[205];
int n,a,b;
void bfs(int x)
{
node p,q,n1,n2;
p.x=x;
p.step=0;
vv[x]=1;
que.push(p);
bool flag=false;
while(!que.empty())
{
q=que.front();
que.pop();
int xx=q.x;
if(xx==b)
{
flag=true;
cout<<q.step<<endl;
break;
}
n1.x=xx+aa[xx];
n1.step=q.step+1;
n2.x=xx-aa[xx];
n2.step=q.step+1;
if(n1.x>=1&&n1.x<=b&&!vv[n1.x])
{
que.push(n1),vv[n1.x]=1;
}
if(n2.x>=1&&n2.x<=b&&!vv[n2.x])
{
que.push(n2),vv[n2.x]=1;
}
}
if(!flag)
cout<<"-1"<<endl;
return ;
}
int main()
{
int i;
cin>>n>>a>>b;
for(i=1; i<=n; i++)
cin>>aa[i];
bfs(a);
return 0;
}