休闲时刻看看神经网络方面的书,发现了修道士和野人的问题,不禁勾引起我写算法的欲望,曾经的三只大老虎三只小老虎过河问题、人狼羊白菜过河问题、汉诺塔、哈夫曼等等各种算法瞬间在脑海中约隐约现,修道士和野人问题我以前好像没有解开,中午吃饭的时候在脑海中重新构造思路,下午耗了点时间把它干掉。(算法不在代码里,而在思想中;所以尽量不要看我的代码,而要仔细分析我写的思路)
题目:
设有3个修道士和3个野人来到河边, 打算用一条船从河的左岸渡到河的右岸。但该船每次只能装载两个人, 在任何岸边野人的数目都不得超过修道士的人数, 否则修道士就会被野人吃掉。假设野人服从任何一种过河安排, 请问如何规划过河计划才能把所有人都安全地渡过河去。
首先考虑总共有(3+1)*(3+1)= 16 种不同的状态(因为左岸可以有0,1,2,3个传教士,左岸可以有0,1,2,3个野人),所以可以考虑使用穷举法。
使用如下C#程序语言:
int MaxNum = 3;for (int monk = MaxNum; monk >= 0; monk--)
{for (int savage = MaxNum; savage >= 0; savage--)
{
Console.Write("{ {" + monk + "," + savage + "},{" + (MaxNum - monk) + "," + (MaxNum - savage) + "}}");
}
Console.Write("\n");
}
生成16种状态图↓↓↓↓↓↓↓↓↓↓↓
状态图含义:
{a,b}:a,左岸修道士数量;b,左岸野人数量。
--------仅考虑左岸传教士和野蛮人数量(所有状态图)------------------------{3,3} {3,2} {3,1} {3,0}
{2,3} {2,2} {2,1} {2,0}
{1,3} {1,2} {1,1} {1,0}
{0,3} {0,2} {0,1} {0,0}
其中{3,3}是起始状态图;{0,0}是终止状态图。
去除在任何岸边野人的人数超过修道士的人数,保留所有可满足的状态图:
--------仅考虑左岸传教士和野蛮人数量(符合要求状态图)----------------------{3,3} {3,2} {3,1} {3,0}
{2,2}
{1,1}
{0,3} {0,2} {0,1} {0,0}
可知,左岸修道士和野人的总数是先减少、再增加、再减少、再增加...直到左岸的总人数为零(这个由船行动的方向决定的,请仔细思考),所求的最终状态图 {0,0},而且每次增减人数最多为2个(条件提示:该船每次只能装载两个人),由此可知左岸总人数的增减趋势是: -1或-2、+1或+2、-1或-2、+1或+2...。
左岸人头数作为参照: