1.问题的提出
3名商人各带1个随从乘船渡河,一只小船只能容纳2人,由他们自己划行。在河的任何一岸当随从的人数多于商人数时,商人就会有危险。但是如何乘船渡河的大权掌握在商人们手中,商人们怎样才能安全渡河呢?
这就是著名的商仆渡河问题,对于这类智力游戏经过一番逻辑思索是可以找出解决办法的。这里要求将问题推广至商仆对数任意、船只容量也任意的一般情况下,建立数学模型,并编程求解。
2.模型建立与符号说明
记商仆对数为m,船容量为c人。
记第k次渡河前此岸的商人数为xk,随从数为yk,k=1,2,…,xk,yk=0,1,2,…,m,
将二维向量sk=(xk,yk)定义为状态,安全渡河条件下的状态集合定义为允许状态空间,记做S
不难验证,S对此岸和彼岸都是安全的。
记第k次渡船上的商人数为uk,随从数为vk,将二维向量dk=(uk,vk)定义为决策dk,允许决策集合记作D,由小船的容量可知
因为k为奇数时船从此岸驶向彼岸,k为偶数时船由彼岸驶回此岸,所以状态sk随决策dk变化的规律称状态转移律。
这样,制定安全渡河方案归结为如下的多步决策模型:
求决策
使状态,按照转移律(3),由初始状态
经过有限步n到达终止状态
详细问题描述见下图:
这里采用BFS算法(广度优先搜索算法)编程求解商仆过河问题。BFS算法是最经典的图搜索算法之一,在本题中可以保证找到的解为最短路径,即所求方案过河总步数最少,其算法描述如下:
建立一个状态队列q,这是一个先进先出的队列。
(1)将起始状态即(n,n)点加入队列q,标记(n,n)点为已访问。
(2)将q的首节点出队,再将所有该节点可达的未被访问的允许状态加入队列q
(3)将所有新加入的状态标记为已访问,如果其中有终止状态(0,0),则问题有解,算法结束。
(4)如果队列q为空,则问题无解,算法结束。
(5)转至(2)执行
分析:
观察BFS算法的执行过程,算法首先将距离起始状态为1次状态转移的所有状态加入队列,如果其中没有终止状态,则继续将所有距离起始状态为2次状态转移的状态加入队列……
由于队列是先进先出的,可以始终保证所需状态转移步数最少的状态排在队列的最前部,并首先由他们扩展下一层状态。
所以加入队列的每个状态都是以最短路径(最少的状态转移步数)到达的,因为如果有更短的路径存在,则此路径上的状态一定会被更早扩展,更早加入状态队列(所需步数少的状态排在状态队列的前部)。
当终止状态加入队列时,到达终止状态的路径也是最短路径,即求得一个所需状态转移步数最少的过河方案。
若某时刻状态队列为空且始终未到达终止状态,则说明所有自起始状态可达的节点均已被访问,且其中没有终止状态,即终止状态不可达,问题无解。
该问题商仆对数和船容量之间的关系与问题是否有解的分析: