程序员眼中的《盗梦空间》

327 阅读3分钟

不同人眼中的递归

img

你眼中的盗梦空间:不停做梦

img

程序员眼中的盗梦空间

那什么是递归?

img

自己调用自己,最简单的一个案例就是阶乘的问题

1! = 1 | 2! = 2x1 | 3! = 3x2x1 | => f(n) = n x f(n-1) 【当n=1结束】

递归有三个需要知道

这个递归要做什么?

这个递归怎么结束?

当程序执行到一个方法时,就会开辟一个独立的空间(栈),而且其中变量互不影响

《盗梦空间》场景重现

这个递归要做什么?=> 盗梦空间中做了什么

其实做梦就是一个递归,如果睡觉/下药那么就会做梦

在梦中在睡觉/给下药 那么又做梦,目前是梦中梦

第三层在做梦,就是梦中梦中梦......

用程序可以这么表示

    void dream(String sleep) {
        dream("做梦 / 下药 / 听音乐 / 猛烈撞击");
    }

这样会无限做梦,电影中到第五层之后人的脑子就已经不行了,会烧坏脑子,虽然程序比人脑强上不少,可以循环很多次,但架不住它快啊,烧的比人脑还要快,最终会导致栈溢出,程序停止

所以结束条件就显得十分重要,先来看盗梦中是怎么结束的?

img

听音乐/收到猛烈撞击 会醒过来,回到上一层梦境中,那么程序就变为了这样

    void dream(String sleep) {
        if ("听音乐".equals(sleep) || "猛烈撞击".equals(sleep)) {
            //返回上一层
            return;
        }
        dream("做梦 / 下药 / 听音乐 / 猛烈撞击");
    }

就会开辟一个独立的空间(栈)也好理解,没有做梦空间还怎么做梦?

方法局部的变量是独立的,不会相互影响。总不能第2层做梦会影响第一层的人(当然除了死掉,不过那个算结束条件)

递归场景复现

马踏棋盘问题---一个经典的回溯问题

img

问题描述

如果给定一个m x n的棋盘,在给定一个马儿棋子的初始位置,按照马走日的规则,如何可以在每个方格只进入一次的情况下,走完整个棋盘。

当然,存在棋盘或者有些起始点不能使马儿走完整个棋盘的情况。

问题解析

马儿在任意一个点,总是会有可走的选择,如果可以走的话,选取一个点走,走不通的话就返回上一步,重新考虑下一个点进行尝试

Java实现

void DFS(int[][] act,int i, int j,int step) {
    //将马儿当前位置置为已使用,记录当前步数
    act[i][j] = step;
    if (step == act.length * act.length) {
        //如果达到预定步数,则打印,并退出程序
        print(act);
        System.exit(0);
    }
    //得到可以落子的坐标集合
    List<Luozi> ls = next(act, i, j);
    for (Luozi l : ls) {
        //递归调用可用坐标
        DFS(act,l.i,l.j,step+1);
    }
    //如果没有达到预定步数,将此点置为0,进行回溯
    if (step < act.length * act.length) {
        act[i][j] = 0;
    }
}

结果输出

19	8	11	28	17	2	
10	27	18	1	12	29	
7	20	9	30	3	16	
26	31	24	15	34	13	
21	6	35	32	23	4	
36	25	22	5	14	33	

以上只提供了核心方法,如需要,源代码请到git上查看:leidl97/algorithm-src