w3 下推式堆栈

7-1 汉诺塔的非递归实现

分数 25

 

全屏浏览题目

 

切换布局

作者 DS课程组

单位 浙江大学

借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b, c),即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”),并保证每个移动符合汉诺塔问题的要求。

输入格式:

输入为一个正整数N,即起始柱上的盘数。

输出格式:

每个操作(移动)占一行,按柱1 -> 柱2的格式输出。

输入样例:

3

输出样例:

a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c

#include<stack>
#include<iostream>
using namespace std;
char s[3] = { 'a', 'b', 'c' };
stack<int> a[3];
bool move(int before, int after)
{
    if (a[before].empty())
        return false;
    if (!a[after].empty()){
        if (a[after].top() - a[before].top() < 0)
            return 0;
    }
    a[after].push(a[before].top());//依次将栈中栈顶元素移至中转栈
    a[before].pop();
    printf("%c -> %c\n", s[before], s[after]);
    return true;
}
int main()
{
    int N, count = 0;
    cin >> N;
    for (int i = 0; i < N; i++)
        a[0].push(N - i);//初始化第一个栈,也就是a[N]放在栈底,a[0]在栈顶
    if (N % 2 == 1)
    {
        s[1] = 'c';
        s[2] = 'b';
    }
    while (++count){
        move((count - 1) % 3, count % 3);
        if (!move((count - 1) % 3, (count + 1) % 3))
        if (!move((count + 1) % 3, (count - 1) % 3))
            break;
    }
    return 0;
}

 

7-2 表达式转换

分数 25

 

全屏浏览题目

 

切换布局

作者 DS课程组

单位 浙江大学

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

输入格式:

输入在一行中给出不含空格的中缀表达式,可包含+-*/以及左右括号(),表达式不超过20个字符。

输出格式:

在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。

输入样例:

2+3*(7-4)+8/4

输出样例:

2 3 7 4 - * + 8 4 / +
#include <stdio.h>
#include <string.h>
 
char stack[50], str[50], post[50]; // 符号栈,表达式字符串,输出栈
int top1 = -1, top2 = -1;
 
char Pop( char c )
{
    if (c == 'D') return '/';
    if (c == 'C') return '*';
    if (c == 'B') return '+';
    if (c == 'A') return '-';
}
 
void Compare( char c ) // 传入字符来比较优先级进而对stack执行相应的操作
{
    if (c == ')') // 如果遇到右括号
    {
        while (stack[top1] != '(' && top1 != -1) // 一直出栈直到遇到第一个左括号或栈空
        {
            post[++top2] = Pop(stack[top1]); // 弹出到输出栈
            post[++top2] = ' ';
            stack[top1--] = '\0'; // 栈顶下移
        }
        stack[top1--] = '\0'; // 此时stack[top1]为左括号,直接弹出即可
    }
    else // 如果是其他的操作符
    {
        while (stack[top1] >= c && stack[top1] != '(' && top1 != -1) // 一直出栈直到遇到优先级更小或者左括号或栈空
        {
            post[++top2] = Pop(stack[top1]); // 弹出到输出栈
            post[++top2] = ' ';
            stack[top1--] = '\0'; // 栈顶下移
        }
        stack[++top1] = c;
    }
}
 
int main(void)
{
    scanf("%s", str);
    for (int i = 0; str[i] != '\0'; i++)
    {
        if (str[i] == '(')
            stack[++top1] = str[i]; // 左括号直接入栈
        else if (str[i] == '-' && (i == 0 || str[i - 1] == '(')) // 负号进入输出栈
            post[++top2] = str[i];
        else if (str[i] == '+' && (i == 0 || str[i - 1] == '(')) // 遇到正号直接跳过
            continue;
        else if (str[i] == '-' && i !=0 && str[i - 1] != '(') // 减号
            Compare('A');
        else if (str[i] == '+' && i != 0 && str[i - 1] != '(') // 加号
            Compare('B');
        else if (str[i] == '*') // 乘号
            Compare('C');
        else if (str[i] == '/') // 除号
            Compare('D');
        else if (str[i] == ')') // 右括号
            Compare(')');
        else
        { // 对待运算符外的字符,最好的方法是一视同仁,只在运算符上进行限制
            post[++top2] = str[i];
            if (str[i + 1] == '+' || str[i + 1] == '-' || str[i + 1] == '*'
                || str[i + 1] == '/' || str[i + 1] == '(' || str[i + 1] == ')' || str[i + 1] == '\0')
                post[++top2] = ' '; // 输出一位空格
        }
    }
 
    while (top1 != -1) // 栈中剩余运算符全部输出
    {
        post[++top2] = Pop(stack[top1--]);
        post[++top2] = ' ';
    }
    if (post[top2] == ' ')
        post[top2--] = '\0'; // 如果结尾是多余空格则删除掉
    printf("%s", post);
 
    return 0;
}

 

7-3 出栈序列的合法性

分数 25

 

全屏浏览题目

 

切换布局

作者 陈越

单位 浙江大学

给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, ..., N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5、N=7,则我们有可能得到{ 1, 2, 3, 4, 5, 6, 7 },但不可能得到{ 3, 2, 1, 7, 5, 6, 4 }。

输入格式:

输入第一行给出 3 个不超过 1000 的正整数:M(堆栈最大容量)、N(入栈元素个数)、K(待检查的出栈序列个数)。最后 K 行,每行给出 N 个数字的出栈序列。所有同行数字以空格间隔。

输出格式:

对每一行出栈序列,如果其的确是有可能得到的合法序列,就在一行中输出YES,否则输出NO

输入样例:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

输出样例:

YES
NO
NO
YES
NO
#include<iostream>
#include<bits/stdc++.h>
using namespace std;


int main()
{
	int i, j;
    int n,m,k;
	cin>>m>>n>>k;
	int a[k][n], s[k];
	for(i = 0;i < k;i++)
	{
		for(j = 0;j < n;j++)
		{
			cin>>a[i][j];
		}
	} 
	
	for(i = 0;i < k;i++)
	{
		stack<int> st;
		int bj = 0;
		for(j = 1;j <= n;j++)
		{
			if(st.size() < m)
				st.push(j);
			else
				break;//栈满
			while(!st.empty())
			{
				if(st.top() != a[i][bj])
					break;
				else
				{
					st.pop();
					bj++;
					continue;
				}
			}
		}
		if(st.empty())
			s[i] = 1;
		else
			s[i] = 0;
	} 
    for(i = 0;i < k;i++)
    if(s[i])
			cout<<"YES"<<endl;
	else
		cout<<"NO"<<endl;
	return 0;
}

7-4 包装机

分数 25

 

全屏浏览题目

 

切换布局

作者 陈越

单位 浙江大学

一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道,放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时,活塞向左推动,将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时,机械手将抓取筐顶部的一件物品,放到流水线上。图 2 显示了顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态。

7570593fbec4880bb0d31c2a181db83e.jpeg

图1 自动包装机的结构

92d56ba17a32f8e53c851bbff67ec001.jpeg

图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态

一种特殊情况是,因为筐的容量是有限的,当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落。此外,如果轨道已经空了,再按对应的按钮不会发生任何事;同样的,如果筐是空的,按 0 号按钮也不会发生任何事。

现给定一系列按钮操作,请你依次列出流水线上的物品。

输入格式:

输入第一行给出 3 个正整数 N(≤100)、M(≤1000)和 Smax​(≤100),分别为轨道的条数(于是轨道从 1 到 N 编号)、每条轨道初始放置的物品数量、以及筐的最大容量。随后 N 行,每行给出 M 个英文大写字母,表示每条轨道的初始物品摆放。

最后一行给出一系列数字,顺序对应被按下的按钮编号,直到 −1 标志输入结束,这个数字不要处理。数字间以空格分隔。题目保证至少会取出一件物品放在流水线上。

输出格式:

在一行中顺序输出流水线上的物品,不得有任何空格。

输入样例:

3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1

输出样例:

MATA
//L2-1 包装机
#include <iostream>    vxgzh:xtsn
using namespace std;
#include <stack>
#define N 105
stack <char> sta;
string s[N];
 
int main()
{
	int n,m,smax,i,x;
	int pi[N]={0};   //记录每条轨道最左边物品的下标/位置 
	cin>>n>>m>>smax;  //输入 
	char c;
	cin.ignore();  //忽略上一次cin输入最后面的换行符
	 
	for(i=0;i<n;i++)  //输入每条轨道的物品信息 
		cin>>s[i];
		
	while(1)
	{
		cin>>x;    //输入按下的按钮 
		if(x==-1)
			break;
		else if(x==0&&!sta.empty())
		{
			c=sta.top();   //从筐中抓出 
			cout<<c;sta.pop();
		}
		else if(x>0)
		{
			if(pi[x-1]<m)
			{
				if(sta.size()==smax)   //框已满 
				{
					c=sta.top();    //从筐中抓出
					cout<<c;sta.pop();
				}
				c=s[x-1][pi[x-1]];pi[x-1]++;	 
				sta.push(c);   //推进筐 
			}			
		}			
	}	
	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

102101222_张凯权

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

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

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

打赏作者

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

抵扣说明:

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

余额充值