参考《算法竞赛进阶指南》p.49

题目链接:https://www.acwing.com/problem/content/description/131/

递推与递归的宏观描述

对于一个待求解的问题”,当它局限在某处边界、某个小范围或者某种特殊情形时,其答案往往是已知的。如果能够将该解答的应用场景扩大到原问题的状态空间,且扩展过程的每个步骤具有相似性,就可以考虑使用递推或者递归求解。以已知的“问题边界”为起点向“原问题”正向推导的扩展方式就是递推。然而在很多时候,推导路线难以确定,这时以“原问题”为起点尝试寻找把状态空间缩小到已知的“问题边界”的路线,再通过该路线反向回溯的遍历方式就是递归。我们通过两幅图来表示递推与递归的差别。

左侧图中,有几个人是原问题,从原问题往前推导是递推。于是从二叉树的最后一层往前推,推导到第一层则可以算出原问题的答案。

右侧图中,几个苹果是原问题。但是在这棵二叉树中,你并不知道有几层和结点的分布情况。对每一个子问题都是一颗二叉树,遍历左右子数,求出苹果,然后往回返回苹果数目。我们刚才也提到,使用递推或递归要求“原问题”与“问题边界”之间的每个变换步骤具有相似性,这样我们才能够设计一段程序实现这个步骤,将其重复作用于问题之中。换句话说,程序在每个步骤上应该面对相同种类的问题,这些问题都是原问题的一个子问题,可能仅在规模或者某些限制条件上有所区别,并且能够使用“求解原问题的程序”进行求解。

对于递归算法,有了上面这个前提,我们就可以让程序在每个变换步骤中执行三个操作:

1.缩小问题状态空间的规模。这意味着程序尝试寻找在“原问题”与“问题边界”之间的变换路线,并向正在探索的路线上迈出一步。

2.尝试求解规模缩小以后的问题,结果可能是成功,也可能是失败。

3.如果成功,即找到了规模缩小后的问题的答案,那么将答案扩展到当前问题,如果失败,那么重新回到当前问题,程序可能会继续寻找当前问题的其他变换路线,直至最终确定当前问题无法求解。

在以上三个操作中有两点颇为关键。-是“如何尝试求解规模缩小以后的问题”。因为规模缩小以后的问题是原问题的一个子问题,所以我们可以把它视为一个新的“原问题”由相同的程序(上述三个操作)进行求解,这就是所谓的“自身调用自身”。二是如果求解子问题失败,程序需要重新回到当前问题去寻找其他的变换路线,因此把当前问题缩小为子问题时所做的对当前问题状态产生影响的事情应该全部失效,这就是所谓的“回溯时还原现场”。上面这类程序就是“递归”的遍历方式,其整体流程如下图所示。

可以看到,递归程序的基本单元是由“缩小”“求解” “扩展” 组成的种变换步骤,只是在“求解”时因为问题的相似性,不断重复使用了这样一种变换步骤, 直至在已知的问题边界上直接确定答案。对于其中任意一条从“原问题”到“问题边界”的变换路线(图中实线圈出的路径),横向来看,它的每层是次递归程序体的执行;纵向来看,它的左右两边分别是寻找路线和沿其推导的流程。为了保证每层的“缩小”与“扩展”能够衔接在同形式的问题上,“求解” 操作自然要保证在执行前后程序面对问题的状态是相同的,这也就是“还原现场”的必要性所在。

对于题目中问题:

面对任何一个状态我们只有两种选择:

1.把下一个数进栈

2.把当前栈顶元素出栈

先进行第二步操作比第一步操作的字典序小。

import java.util.LinkedList;
import java.util.Scanner;
import java.util.Stack; public class Main {
static LinkedList<Integer> list=new LinkedList<Integer>();
static Stack<Integer> stack=new Stack<Integer>();
static LinkedList<Integer> ans=new LinkedList<Integer>();
static int cnt=20;
static int n=0;
static void dfs() {
if (cnt==0) {
return;
}
if (ans.size()==n) {
for (Integer integer : ans) {
System.out.print(integer);
}
System.out.println();
cnt--;
return;
} if (stack.size()!=0) {
int x=stack.pop();
ans.add(x);
dfs();
//System.out.println(ans.peekLast()==x);
stack.push(x);
ans.removeLast(); }
if (list.size()!=0) {
int s=list.getLast();
list.removeLast();
stack.push(s);
dfs();
list.add(s);
stack.pop();
}
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
for (int i = n; i >=1; i--) {
list.add(i);
}
dfs();
} }

  

0x11栈之火车进栈的更多相关文章

  1. 火车进栈(进出栈的模拟,dfs爆搜)

    这里有n列火车将要进站再出站,但是,每列火车只有1节,那就是车头. 这n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从 ...

  2. C语言实现链栈的初始化&进栈&出栈&读取栈顶元素

    /*链表实现栈的一系列操作*/ #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 typede ...

  3. C语言实现顺序栈的初始化&进栈&出栈&读取栈顶元素

    /*顺序表实现栈的一系列操作*/ #include<stdio.h> #include<stdlib.h> #define Stack_Size 50 //设栈中元素个数为50 ...

  4. 0x11栈之Editor

    参考链接:https://blog.csdn.net/SSLGZ_yyc/article/details/81700623 对顶栈的思想: 建立两个栈,栈A存储从序列开头到当前光标的位置的一段序列,栈 ...

  5. tyvj/joyoi 1336 火车进栈

    比原题水了很多(因为原题要高精度) 输出字典序前20种出栈序列. 其实是贪心题:我们每次确定一个出栈的数. 当栈里有数时,字典序显然比从后面拿数要小,所以先搜这个. 之后依次搜后面队列里的数,因为字典 ...

  6. 0x11 栈

    这个不难吧,算是常识了..毕竟也是刷过USACO的人 对顶栈这东西前几天才遇到过,好像和在线求中位数那东西放一起了吧 单调栈倒是没什么...贴个代码算了.一开始有点蠢的每个位置算,后来发现出栈再算就行 ...

  7. luogu P1044 火车进出栈问题(Catalan数)

    Catalan数就是魔法 火车进出栈问题即: 一个栈(无穷大)的进栈序列为 1,2,3,4,...,n 求有多少个不同的出栈序列? 将问题进行抽象, 假设'+'代表进栈, 则有'-'代表出栈 那么如果 ...

  8. 问题-栈S最多能容纳4个元素,现有6个元素按A、B、C、D、E、F顺序进栈,问可能的出栈顺序。

    住栈的特性:对于取出栈内元素每次只能从栈顶开始取(后进先出(栈满时,只能先出后进)) 由于栈内只能容纳4个元素: 所以 E F不可能第一个出栈: 当栈内少于四个元素时 既可以选择进栈,也可以选择出栈 ...

  9. [实战演练]Intel面试题目 - 进栈出栈顺序问题

    电话面试中写C++,逻辑比较清楚的一个题目,一紧张就不能好好地写下来,漏洞百出.以前经常在完善的编译环境中写代码,换了一个白板子上写反而写的不通顺了,犯了一些基础错误,比如stack中的首个元素是to ...

随机推荐

  1. RuntimeError: implement_array_function method already has a docstring

    根源:Numpy/Scipy/Pandas/Matplotlib/Scikit-learn 出现冲突 解决办法: pip uninstall scikit-learn pip uninstall ma ...

  2. Spring cloud之Eureka(二)注册中心高可用

    背景 在实际的生产环境中,注册中心如果只有一个,是很危险的,当这个注册中心由于各种原因不能提供正常服务或者挂掉时,整个系统都会崩溃,这是很致命的的,所以在Spring cloud 设计之初就考虑到了注 ...

  3. Zynq系列FPGA如何固化bit文件到QSPI_Flash

    最近由于项目需要,要将bit文件固化到zedboard的flash中,使程序上电自启,断电不丢失. 我们知道,一般板级调试的时候都是直接下载bit流到FPGA就行,固化到Flash的话,也是先生成.m ...

  4. C# 字典Dictionary

    Dictionary<TKey, TValue> 泛型类提供了从一组键到一组值的映射.通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictionary<TKey, T ...

  5. 2019年 Gratner数据分析平台对比 - PowerBI大幅领先

    先睹为快,看看你正在用的工具在哪里? 文末见2017-2018图 对比2019年, 1.ThoughtSpot好像发展很快 2.IBM...... 3.Microstrategy好像表现还不错 4.L ...

  6. VisualVM监控远程服务器JVM

    VisualVM是JDK自带的一款全能型性能监控和故障分析工具,包括对CPU使用.JVM堆内存消耗.线程.类加载的实时监控,内存dump文件分析,垃圾回收运行情况的可视化分析等,对故障排查和性能调优很 ...

  7. 用原生js+canvas实现五子棋

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  8. winrar目录穿越漏洞

    地址: 参考: https://research.checkpoint.com/extracting-code-execution-from-winrar/ POC: https://github.c ...

  9. CentOS 7 配置DHCP中继代理服务

    DHCP服务器只作用于局域网同一网段内,客户端是通过广播消息来获得DHCP服务器响应后才能得到IP地址的,但广播消息不能跨越子网,那么如何让客户端获取到DHCP服务器提供的IP地址呢?这就是DHCP中 ...

  10. pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0

    原因: 使用了多线程,多线程共享了同一个数据库连接,但每个execute前没有加上互斥锁 方法: 方法一:每个execute前加上互斥锁 lock.acquire()         cursor.e ...