网易极客战记官网codecombat|编程解决算法问题「农民过河」,穷举思想轻松学(二)

用极客战记学习编程,孩子学习的并非只有代码。
网易极客战记官网codecombat|编程解决算法问题「农民过河」,穷举思想轻松学(二)
当我们遇到如「农夫过河」之类像脑筋急转弯的算法题,我们动动脑子,或许很快就能直接想出一种解法。

但如果我们想找出所有的解法,是不是就有一定的难度了呢?如何更快更全地找出所有的过河方法呢?

因此,我们需要学会一种更有条理更系统化的处理算法:「穷举法」

在上一节课里,我们已经对题目进行了分析解析,把一个深奥复杂的文字题,通过一系列的转化,变成了一个简单易懂,更适合电脑处理的数字题目。

第二步:优化运算过程

根据上方的分析,我们把问题转化成了在符合条件的情况下,把(0,0,0,0)转化成(1,1,1,1)。此时的题目已经变的简单易懂,接下来就要开始解决题目了。

穷举法的本质就是把所有的答案都尝试一遍,因此穷举法会有比较复杂的运算过程,例如:

第一次过河,狮鹫带士兵过河,结果是

(1,1,0,0)

第二次过河,狮鹫带食人魔过河,结果是

(1,1,1,0)

由于过河必须要狮鹫的帮助,因此,每次过河完的结果,狮鹫一定是与过河人在同一个位置上的。

所以,我们能够得到四种表示过河方式的状态:

(1,0,0,0):狮鹫自己过河

(1,1,0,0):狮鹫带士兵过河

(1,0,1,0):狮鹫带食人魔过河

(1,0,0,1):狮鹫带农民过河

那么再看,如果我们要表示,第一次过河,狮鹫带食人魔过河,可以这样表示:

过河前(0,0,0,0);

过河方式:(1,0,1,0);

过河结果:(1,0,1,0);

第二次过河,狮鹫带士兵过河:

① 先让狮鹫飞回来:

过河前(1,0,1,0);

过河方式:(1,0,0,0);

过河结果:(0,0,1,0);

② 再让狮鹫带士兵过河:

过河前(0,0,1,0);

过河方式:(1,1,0,0);

过河结果:(1,1,1,0);

看看上面的三组过程,仔细观察。

你会发现,当0和1相遇,它的结果就会变成1,当1和1相遇,它的结果会变成0。

因此我们还可以把过河的情况,用更简洁的方式表示出来。

定义一个运算规则:0+1=1,1+1=0

因此,过河就可以这样表示:

(0,0,0,0)+(1,0,1,0)=(1,0,1,0)

(1,0,1,0)+(1,0,0,0)=(0,0,1,0)

然后,我们就可以开始穷举啦。

第三步:开始穷举

最初四个人物的状态为:(0,0,0,0)

四种过河方式为:

(1,0,0,0):狮鹫自己过河

(1,1,0,0):狮鹫带士兵过河

(1,0,1,0):狮鹫带食人魔过河

(1,0,0,1):狮鹫带农民过河

第一次过河:

第一次过河的运算式我们可以这么写:
网易极客战记官网codecombat|编程解决算法问题「农民过河」,穷举思想轻松学(二)
看看最后得出的四个结果,我们拿题目的条件来检验一下。

第一个结果(1,0,0,0),只有狮鹫过河,这是没有意义的过河,所以这一结果不可取。

第二个结果(1,1,0,0),狮鹫带士兵过河,那么这样农民和食人魔就都是0,单独呆在了一块,农民就会受到食人魔的攻击,因此也是不行的。

第三个结果(1,0,1,0),狮鹫带食人魔过河,士兵和农民在一边,狮鹫和食人魔在一边,不会发生问题,这个结果可行。

第四个结果(1,0,0,1),狮鹫带农民过河,士兵和食人魔呆在了一块,这也不行。

因此可以得出,第一次过河的正确过河方式是:

(0,0,0,0)+(1,0,1,0)=(1,0,1,0)狮鹫带食人魔过河

第二次过河:

而第二次过河,需要先让狮鹫飞回右边,同样也是有四种过河方式:

第一步,先让狮鹫飞回右边,同样也是有四种过河方式:
网易极客战记官网codecombat|编程解决算法问题「农民过河」,穷举思想轻松学(二)
但,此时这边只有食人魔和狮鹫,因此可取的过河方式仅有(1,0,0,0)和(1,0,1,0):
网易极客战记官网codecombat|编程解决算法问题「农民过河」,穷举思想轻松学(二)
对结果进行分析,若是第二种方式,(0,0,0,0)等于又变回没过河前的状态了,不可取,因此结果为让狮鹫自己飞回去:(0,0,1,0)

第三次过河:

然后再拿上面的结果进行第三次过河的运算:
网易极客战记官网codecombat|编程解决算法问题「农民过河」,穷举思想轻松学(二)
同样,再次分析,得出结果。

(1,0,1,0)等于又回到了上一步的状态,因此不可取;

(1,1,1,0)可行

(1,0,1,1)可行

每次都取可行的结果进行运算,直到算出(1,1,1,1),如此下去,就能利用穷举,把所有的过河方式给穷举出来啦。

穷举法的利弊

穷举法的思想就是如此,首先对题目和运算过程进行分析,让它能够以更具逻辑的方式表达出来,然后,算出所有的结果并检验是否可行。

虽然<农民过河>就像脑筋急转弯一样简单,但真要找出所有的解决方法,不用算法,直接思考,还是需要一定的时间。

而使用上更有逻辑的穷举法,**甚至无需太多的思考,跟着运算过程一步步算下去,机械化地就能得到所有的正确结果,**精准无误,手动计算都这么方便了,那么用电脑代码实现,只会更快更方便

它的优点就在于,它是一个极其简单易懂的算法。就像解决<农夫过河>问题一样,我们可以十分轻松地把穷举法的思想带进我们的生活问题中使用。

而穷举的缺点十分明显:

穷举的方法很逻辑化,易于执行,但计算所有结果,就为了找出几个正确结果,操作量十分庞大,十分麻烦,如果题目变得更加复杂,那穷举就变得更不实用了。

在未来,你还会学到更多更强大的算法,与穷举法相比,它们还可以更智能地得到条件,把无用运算筛选掉,提高效率。

如果题目变得更为复杂,哪怕是电脑,穷举都需要非常久的工作时间,远远不如其他先进的算法。

事实上,无论哪种算法,都有利弊,都有比它先进的算法,可见,唯有不断地学习,掌握越来越多先进的知识,才是最先进的算法。

本攻略发于极客战记
极客战记——学编程,用玩的!