人、狼、羊、菜安全渡河问题 安全渡河问题又称作“人狼羊菜”问题,其具体描述为:一个人带着一条狼、一只羊、一筐白菜过河但由于船太小,人一次只能带一样东西乘船过河。狼和羊、羊和白菜不能单独留在同岸,否则羊或白菜会被吃掉。该问题可使用图论中的最短路算法进行求解。 问题分析 根据题意,人不在场时,狼要吃羊,羊要吃菜,因此,人不在场时,不能将狼与羊、羊与菜留在河的任一岸。可用四维向量v=(m,n,p,q)来表示状态, m表示人,n代表狼,p代表羊,q代表白菜,且m,n,p,q ∈{0,1},0代表在对岸,1代表在此岸。例如,状态(0,1,1,0)表示人和菜在对岸,而狼和羊在此岸,这时人不在场,狼要吃羊,因此,这个状态是不可行的。 通过穷举法将所有可行的状态列举出来,可行的状态有 (1,1,1,1),(1,1,1,0),(1,1,0,1),(1,0,1,1),(1,0,1,0),(0,1,0,1),(0,1,0,0),(0,0,1,0),(0,0,0,1),(0,0,0,0)。 可行状态共有十种。每一次的渡河行为改变现有的状态。现构造赋权图G=(V,E,W),其中顶点集V={v1,…, v10}中的顶点(按照上面的顺序编号)分别表示上述10个可行状态,当且仅当对应的两个可行状态之间存在一个可行转移时两顶点之间才有边连接,并且对应的权重取为1,当两个顶点之间不存在可行转移时,可以把相应的权重取为∞。 因此问题变为在图G中寻找一条由初始状态(1,1,1,1)出发,经最小次数转移到达最终状态(0,0,0,0)的转移过程,即求从状态(1,1,1,1)到状态(0,0,0,0)的最短路径。 该问题难点在于计算邻接矩阵,由于摆渡一次就改变现有状态,为此再引入一个四维状态转移向量,用它来反映摆渡情况。用1表示过河,0表示未过河。例如,(1,1,0,0)表示人带狼过河。状态转移只有四种情况,用如下向量表示: (1,0,0,0),(1,1,0,0),(1,0,1,0),(1,0,0,1) 现在规定状态向量与转移向量之间的运算为 0+0=0,1+0=1,0+1=1,1+1=0 通过上面的定义,如果某一个可行状态加上转移向量得到的新向量还属于可行状态,则这两个可行状态对应的顶点之间就存在一条边。用计算机编程时,可以利用普通向量的异或运算实现,具体的Matlab程序如下: clc,clear a=[1 1 1 1;1 1 1 0;1 1 0 1;1 0 1 1;1 0 1 0; 0 1 0 1;0 1 0 0;0 0 1 0;0 0 0 1;0 0 0 0];%每一行是一个可行状态 b=[1 0 0 0;1 1 0 0;1 0 1 0;1 0 0 1];%每一行是一个转移状态 w=zeros(10);%邻接矩阵初始化 for i=1:9 for j=i+1:10 for k=1:4 if findstr(xor(a(i,:),b(k,:)),a(j,:)) w(i,j) = 1; end end end end w = w,; %变成下三角矩阵 c = sparse(w); %构造稀疏矩阵 [x,y,z]= graphshortestpath(c,1,10,’Directed’,0) %该图是无向图,Directed属性值为0 h = view(biograph(c,[],’ShowArrows’,’off’,’ShowWeights’,’off’)); %画出无向图 Edges = getedgesbynodeid(h);%提取句柄h中的边集 set(Edges,’LineColor’,[0 0 0];%为例将来打印清除,边画成黑色 set(Edges,’LineWidth’,;%线型宽度设置为 赋权图G之间的状态转移关系如下图所示: 节点6节点7节点9节点8节点10节点1节点3节点2节点4节点5 图 可行状态之间的转移 最终求得的状态转移顺序之一为: 1 6 3 7 2 8 5 10 对应方案为:经过7次渡河就可以把狼、羊、蔬菜运过河,第一次运羊过河,空船返回;第二次运菜过河,带羊返回;第三次运狼过河,空船返回;第四次运羊过河。 另一种方案同理可由图得,请读者自行写出。 参考文献 [1]司守奎,孙玺菁.数学建模算法与应用[M].北京:国防工业出版社,2015. [2]郭强,孙浩.运筹学原理与算法[M].西安:西北工业大学出版社,2006. [3]严蔚敏,吴伟民.数据结构[M].北京:清华大学出版社,2002. 本文来源:https://www.wddqw.com/doc/1c6520b2930ef12d2af90242a8956bec0875a565.html