程式设计解决演算法问题 穷举思想轻松学
我们在数橙科学中python的极客战记很多关卡在向孩子教学程式码的同时,也是在潜移默化地训练孩子的程式设计思维。在最开始的地牢地图中,孩子需要使用“While-True”循环语句,穿过一个又一个结构重复的迷宫(图1)。

在学习“While-True”循环语句的同时,也在训练著使用“循环思维”解决重复问题的能力:
1.发现并拆解重复部分
2.解决重复问题
3.循环执行问题的解决方法
这样,就能只用一段程式码,高效地解决重复问题了。可见,在程式设计中,学习程式码的编写只是基本,更重要的还是掌握运用程式码的程式设计思维。
一、农民过河问题
在程式设计的数道经典算法问题中,有一个“农夫过河”问题:一个农夫带着一只狼,一只羊和一些菜过河。河边只有一条船,由于船太小,只能装下农夫和他的一样东西,在无人看管的情况下,狼要吃羊,羊要吃菜,请问农夫如何才能使三样东西平安过河。
为了用程式码解决这个问题,程序员需要利用“穷举搜寻思想”,尝试所有的过河方案,直到找出正确的过河方案。
二、士兵,食人魔和农民
关卡地址:https://codecombat.163.com/play/level/soldier-ogre-and-peasant?(图2)

关卡介绍:
你需要使用狮鹫,把士兵、食人魔、农民,带去河的对岸,狮鹫每次只能带一个人离开,而食人魔会伤害农民,士兵会攻击食人魔,因此不要让士兵和食人魔单独留在一起,也不要让食人魔和农民单独留在一起。
这一关是和“农夫过河”同类型的问题,就像一个脑筋急转弯,不用程式码,用我们的智慧,动动脑筋,应该很快就能想出解法。
但你能想出一种解法,如果你想找出所有的解法,是不是就有一定的难度了呢?如何更快更全地找出所有的过河方法呢?
在本关,我们可以学习一下如何使用“穷举思想”解决程式设计问题。
三、穷举是什么?
穷举是什么呢?它有着一个高大上的名字,但它的本质却十分的简单朴实。
穷举法的基本思想:根据题目的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到全部情况验证完毕。
简单来说就是:把所有的答案都试一遍,找出正确的答案。
非常的简单粗暴。因此,它也是程式设计常用中效率较低的一种算法。使用穷举法,通常需要三步:解析题目——优化运算过程——开始穷举。我们来试试利用穷举法解决关卡“士兵,食人魔和农民”吧!
四、解析题目
穷举法的第一步就是分析题目,把原本的文字题目,转化成更易于分析,简洁有逻辑的题目型别。
① 题目的物件
题目看似只是三个人的过河问题,但实际上在题目里有四个人物:狮鹫、士兵、食人魔、农民。狮鹫负责帮助大家过河。
② 题目的条件
(1)士兵和食人魔不能单独留在一起;
(2)食人魔和农民也不能单独留在一起。
也就是说,当狮鹫、士兵、食人魔呆在一起的时候,也不会发生问题,因为士兵和食人魔马上就要被狮鹫运走,来不及打架。
③ 题目的状态
我们需要使用狮鹫来帮助他们从右边飞到左边,因此题目具有以下几种可能发生的情况:
1.左边有士兵、食人魔、农民、狮鹫,右边什么都没有。
2.左边有食人魔、农民、狮鹫,右边有士兵。
3.左边有农民、狮鹫,右边有士兵、食人魔。
……等等多种情况
④ 优雅地表示题目
可以看到,用文字标识题目可能发生的情况,十分地复杂。因此,在程式设计中,我们常常会用一些特定的符号来简洁地表达题目可能发生的情况。
看看题目,人物只会有两种状态,在右边(还没过河),在左边(过河了),因此我们可以直接用0、1来表示人物的位置。
0表示还没过河;1表示已经过河。
那么就可以这样表示:(狮鹫、士兵、食人魔、农民)
1. (1,1,1,1)表示所有人物都已过河,到了左边。
2. (1,0,1,1)表示食人魔和农民过了河,士兵还没有。
3.……等等
用这种简洁的方式,把题目的所有情况表示出来就是:共16种状态(图3)。

根据题目的条件,我们可知,有以下几种情况是不可取的:农民和食人魔单独在一起:(0,0,1,1)、(1,1,0,0);士兵和食人魔单独在一起:(0,1,1,0)、(1,0,0,1);还有两种隐含的不可取条件:
只有狮鹫自己在一边:(1,0,0,0),这表示,所有人都没过河,只有狮鹫过河了,而狮鹫本来就是帮助大家过河的,不可能自己单独呆在河的一边。所以这种情况是不会发生的。
那么同理还有:(0,1,1,1)这种情况,所有人都过了河,狮鹫没有过河,这也不会发生。
那么本题的问题就变成了:如何在符合条件的情况下,把(0,0,0,0)转化成(1,1,1,1)。