蓝桥杯训练营——栈和递归

知识准备:

  1. 栈(stack)只允许在栈的一端插入或删除元素,这一端被称为栈顶;另一端称为栈底
  2. 在C++的标准库中,stack在头文件<stack>里面。
  3. stack<T> s定义了一个存储T类型数据的栈s。

在这里插入图片描述

例一:手动实现一个栈

#include<iostream>
using namespace std;
struct Stack{
	int data[10000];
	int top=-1;
	void push(int x){
		top++;
		if(top<10000){
			data[top]=x;
		}else{
			top--;
			cout<<"stack overflow"<<endl;
		}
	}
	void pop(){
		if(top>=0){
			top--;
		}
	}
	int topval(){
		if(top>=0){
			return data[top];
		}
	}
}; 
int main(){
	Stack s; 
	for(int i=1;i<=10;++i){
		s.push(i);
	}
	for(int i=1;i<=10;++i){
		cout<<s.topval()<<" ";
		s.pop();
	}
	return 0;
}

例二:火车出入站

问题描述:

在火车调度站里,我们可以借助类似下图中的轨道,将火车车厢的顺序进行调整。我们都知道,火车的车厢是一节一节的,每一节都可以与前后分离,称为单独的一节。

在这里插入图片描述

这样的设计加上上面的轨道,通过合理的控制,我们就可以调节车厢之间的顺序了。但是并不是所有的出站顺序都是合法的。现在对于一种我们期望的出站顺序,作为火车站长,你需要知道这个顺序是否是合法的。

输入:

第一行输入火车车厢节数

第二行输入火车出站顺序

代码如下:
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int main(){
	int n;
	cin>>n;
	vector<int> a(n);
	for(int i=0;i<n;++i){
		cin>>a[i];
	}
	stack<int> s;
	int cur=1;
	bool f=1; 
	for(int i=0;i<n;++i){
		while(s.empty()||s.top()!=a[i]&&cur<=n){
			s.push(cur);
			cur++;
		}
		if(s.empty()||s.top()!=a[i]){
			f=0;
			break;
		}else{
			s.pop();
		}
	}
	if(f){
		cout<<"legal"<<endl;
	}else{
		cout<<"illegal"<<endl;
	}
	return 0;
}

例三:括号匹配

代码如下:
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
char s[50005];
stack<int> st;
int ans[50005];
int main(){
	scanf("%s",s);
	int len=strlen(s);
	bool f=true;
	for(int i=0;i<len;++i){
		if(s[i]=='('){
			st.push(i+1);
		}else{
			if(!st.empty()){
				ans[i+1]=st.top();
				st.pop();
			}else{
				f=false;
				break;
			}
		}
	}
	if(!st.empty()){
		f=false;
	}
	if(!f){
		printf("no\n");
	}else{
		printf("yes\n");
		for(int i=1;i<=len;++i){
			if(ans[i]){
				printf("%d %d\n",ans[i],i);
			}
		}
	}
	return 0;
}
运行结果:

在这里插入图片描述

例四:汉诺塔1

汉诺塔代码二

例五 :汉诺塔2

问题描述:

现在小明开始玩汉诺塔问题,他放了2片黄金圆盘在第一根柱子上,从上到下依次编号为1~n,1号圆盘最小,n号最大。小明移动第i号圆盘需要花费i点力气,现在啊小明想把圆盘全部移动到第二根柱子上,那么小明完成游戏的最小移动次数和最少消耗的体力是多少?

输入:

输入一个正整数n(1<=n<=60)表示黄金圆盘的个数

输出:

一行输出2个数,第一个表示最小移动次数,第二个表示最小小号的体力,中间用一个空格隔开。

代码如下:
#include<cstdio>
long long f[60+5],g[60+5];
using namespace std;
int main(){
	int n;
	scanf("%d",&n);
	f[1]=g[1]=1;
	for(int i=2;i<=n;++i){
		f[i]=2*f[i-1]+1;
		g[i]=2*g[i-1]+i;
	}
	printf("%lld %lld\n",f[n],g[n]);
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枯木何日可逢春

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值