参考《算法竞赛进阶指南》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. smarty 循环一维关联数组

    <?php $oStatusList = array('1'=>'待投放','2'=>'正在运行','3'=>'暂停','4'=>'已完成','5'=>'已删除') ...

  2. Cassandra数据模型

    Ⅰ.数据模型 1.1 Column 一组包含Name/Value Pair的数据叫Row,其中每一组Name/Value Pair叫Column Column是Cassandra最基本的数据结构,它是 ...

  3. PrimeNG之Input(一)

    Input之AutoComplete --自动完成功能是输入组件,提供实时的建议当打字. Import import {AutoCompleteModule} from 'primeng/primen ...

  4. Django ORM中datetiem数据类型字段无法对比处理办法

    在做商城项目中浏览足迹时,我利用浏览商品的ID和浏览的时间保存到browse表中,然后在我的足迹页面根据最近日期进行展示 条件:每天/个商品只能如一次表 后台代码如下: #存储浏览足迹到browse表 ...

  5. IIS宿主WCF服务*.svc Mime类型映射

    经常会遇到由于.net安装组件缺失,导致发布wcf服务后,访问wcf报.svc请求类型不支持 简单方法就是添加删除程序,修改.net组件安装选项,勾选http激活即可: 或者手工添加映射处理程序 1. ...

  6. 001-zookeeper 简介-paxos算法,zk简介,特点

    一.概述 大数据体系概述 1.1.什么是zookeeper 是Google的Chubby一个开源的实现,是Hadoop的分布式协调服务 它包含一个简单的原语集,分布式应用程序可以基于他实现同步服务,配 ...

  7. angular4脚手架搭建

    Angular4.X安装,创建 1.安装最新的nodejs(node -v ,npm -v) 2.新建文件夹(右键git bash here)npm install -g @angular/cli 3 ...

  8. 学习git之路--1

    1. 在文件内右键选择git.bash2.打开工具后,输入git init 创建.init文件3.git config --global 'sk' 创建用户名4.git config --global ...

  9. SqlServer 字段拼接

    最近入职了新公司,使用的是sql server 之前因为一直使用的都是Mysql,mysql 有专用的GROUP_CONCAT()函数,那么这个就是很方便的啦,只要对结果集进行一个Group By  ...

  10. 阿里云轻量级服务器上JDK及tomcat部署配置

    先下载JDK和tomcat到本地 地址为http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html ht ...