诺兰大神的新作《信条》正在热映,很多人从电影院出来就是一脸懵逼:这到底讲了个啥?
不知道大家有没有看懂,反正小编也是看得云里雾里。这部结合麦克斯韦妖、热力学第二定律等等物理知识,以及各种时间悖论糅合而成的科幻之作给了观众一个全新的设定,和以往所有的时空类科幻电影都不同。
今天我们不做剧情解析,而是从算法的角度来解析《信条》。不止如此,诺兰的其他大作也都可以和算法挂钩。看完这篇文章,你也许会感叹:诺兰怕不是个程序员吧!
信条里最核心的科幻设定就是通过熵减达成逆向时间的操作。
这和回溯算法有着异曲同工之妙:有正向的操作就有反向操作,在深度优先搜索中,我们对参数进行的修改,在递归调用之后,都要改回来。
1 path.add(node)
2 visited.add(node)
3 recursion(path, visited) // (注释:这个就相当于电影中用来逆转时间的机器)
4 path.remove(node) // backtracking
5 visited.remove(node) // backtracking
而最后时间钳形作战的高潮部分也是最让观众疑惑的地方,正派反派、红队蓝队、正向逆向的一套“组合拳”直接把观众打晕!
其实有时候算法面试也是如此:纵使一道题目有千百种方法去解答,我们挠破头皮还想不明白。只能叹一句:是我基础不够扎实!
小编只能用电影里的一句话来安慰大家:别去试图理解它,去感受它。
《盗梦空间》作为诺兰最著名的科幻片之一,在刚上映的时候带给了观众无限的震撼——原来科幻片的脑洞还能这么大?当然小李子的演绎也让这部电影更上一层楼。
《盗梦空间》里层层梦境的设定和递归算法的有着极高的相似度。
假设我们要进入第 i 层梦境,首先要进入第 i-1 层。而递归也是如此,要进入第 i 层递归,首先要完成第 i-1 层递归。
盗梦者在某一层梦境里死亡,回到的是上一层梦境,而不是最初始的梦境。
同样地,在递归算法里面进行 return 的时候,是销毁了当前这一层递归的所有局部变量,回到上一层递归,而不是最开始的递归入口。
1 void recursion(int deep) {
2 if (deep == 0) {
3 return;
4 }
5 recursion(deep + 1);// 递归了上一层梦境,而不是第一层
6 return;// return 代表了销毁
7 }
盗梦者在某一层梦境里死了或者发生了改变,不影响上一层梦境的状态。举例来说,盗梦空间里多层梦境里的小李子虽然都叫小李子,但在这层梦境里沉睡后,下一层里的小李子和上一层完全不相干。
**递归下一层的变量 i 被修改之后,上一层的 i 不受影响。**即使变量是同样的名字,但实际是不同的变量,处于内存的不同位置。
从这个角度看,诺兰的逻辑就有了更加靠谱严谨的解释,也难怪他的科幻电影会让一大堆人着迷,并且大家都为探究电影的“真相”趋之若鹜。
一位士兵设法混上敦刻尔克撤退的救援船,一架战机与德军展开激烈的遭遇战,还有一艘民船义无反顾地支援敦刻尔克,最后所有人事物在敦刻尔克海滩上汇合,完成时间线的收束。
这就是诺导难得的历史战争题材的电影《敦刻尔克》。这种**“分开处理(叙事),然后把处理的结果合并到一起”**的做法,是不是很像我们经常会遇到的“分治法”?
(《敦刻尔克》里最经典的“无声胜有声”的镜头之一)
分治法顾名思义就是“分而治之”。通常我们用来把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。是十分经典的优化算法之一。
1 void divide(int left, int right) {
2 if(left == right) {
3 return;
4 }
5 //divide into parts
6 int mid = (left + right) / 2;
7 divide(left, mid);
8 divide(mid + 1, right);
9 // conquer left to right
10 return;
11 }
这么一解释,小编好像都没法“正常”地看电影了——大半时间都在思考这里用了啥算法逻辑,那里又怎么用编程来解释。诺神的电影,原来就是骗我去二刷的!
大家对诺神的片子还有什么有趣的解读,不妨在评论区留言哦~
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.