欢迎光临散文网 会员登陆 & 注册

北太天元解人、狼、羊、菜渡河问题

2023-12-03 18:53 作者:卢朓  | 我要投稿


%北太天元求解 渡河问题(人、狼、羊、蔬菜)

%某人带狼、羊、蔬菜渡河,有一艘船,每次渡船人最多只能载一物。

%我们知道狼吃羊、羊吃蔬菜,所以在人不在场时,狼和羊不能共存,

%羊和菜不能共存。试问此人最少的渡河次数。


%我们假设河是东西走向的,人、狼、羊、菜开始在北岸,最终的目标是

%人、狼、羊、菜都到了南岸。

% 用一个向量表示人、狼、羊、菜的state(态),如

% (1,1,1,1) 表示人、狼、羊、菜都在北岸

% (1,1,1,0) 表示人、狼、羊在北岸,菜在南岸

% 总共有2^4=16种状态

% 最终要达到的状态是 人、狼、羊、菜都在南岸, 也就是态 (0,0,0,0)

% 我们为了简化问题,还可以先把不可能的状态排除掉,如

% (1,1,0,0) -- 羊和菜都在南岸(人在北岸,狼在北岸)

% (0,0,1,1) -- 羊和菜都在北岸(人在南岸,狼在南岸)

% (1,0,0,0) -- 羊和菜都在南岸(人在北岸, 狼在南岸)

% (0,1,1,1) -- 羊和菜都在北岸(人在南岸, 狼在北岸)

% (0,1,1,0) -- 狼和羊都在北岸 (人在南岸)

% (1,0,0,1) -- 狼和羊都在南岸 (人在北岸)

%

%这些状态和数字的对应

% 二进制 0,0,0,0 对应到 0

% 二进制 i1,i2,i3,i4  对应到 i1*2^3 + i2*2^2+i3*2^1 +i4*2^0

% 其中 i1,i2,i3,i4 分别取值为0,1

%


% 每一个态对应一个节点

%从一个态可以转化为另一个态,我们认为两个节点(这个两个态对应的节点

%连接有一条边。


A = zeros(16,16);

for i=1:16

   for j=1:16

      A(i,j) = has_edge(i-1,j-1);

   end

end


%观测 A^k(16,1) 随着k的增加什么时候开始变成非零,这表明从state (1,1,1,1)

% 到state (0,0,0,0) 开始有了一条长度为k的路径

p = A(16,1);

B = A;

路径长度 = 1;

while p == 0

 B = B*A;

   p = B(16,1);

   路径长度 = 路径长度+1;

end

% 把态转成一个数

% s 是一个长度是4的向量,每个分量是0或1

function n = state_no( s )

   n = s(1)*2^3 + s(2)*2^2 + s(3)*2 + s(4);   

end


% 把state_no 专程state_vec

% n 是0-15之间的整数

function s = state_vec( n )

   s = zeros(4,1);

   s(1) = floor(n/8);

   s(2) = floor( (n-s(1)*8)/4);

   s(3) = floor( (n-s(1)*8-s(2)*4)/2);

   s(4) = n-s(1)*8-s(2)*4-s(3)*2;

end


%判断节点i 和节点j 是否有边连接

% i 和 j 都是 state_no

function b = has_edge(i,j )

   vi = state_vec(i);

   vj = state_vec(j);

   if( vi(1) == vj(1) ) % 两个态之间的变换一定要有人的状态的改变

                         % vi(1) == vj(1) 说明人的状态没有改变,因此没有路径

      b = 0;

      return;

   end


   if(vj(1) == 1) % 人在北岸

         if(vj(2) == 0 && vj(3) == 0) % 狼和羊在南岸

            b = 0;

            return;

         end

         if(vj(3) == 0 && vj(4) == 0) % 羊和菜在南岸

            b = 0;

            return;

         end

   else % 人在南岸

         if(vj(2) == 1 && vj(3) == 1) % 狼和羊在北岸

            b = 0;

            return;

         end

         if(vj(3) == 1 && vj(4) == 1) % 羊和菜在北岸

            b = 0;

            return;

         end

   end


   if(vi(1) == 1) % 人在北岸

         if(vi(2) == 0 && vi(3) == 0) % 狼和羊在南岸

            b = 0;

            return;

         end

         if(vi(3) == 0 && vi(4) == 0) % 羊和菜在南岸

            b = 0;

            return;

         end

   else % 人在南岸

         if(vi(2) == 1 && vi(3) == 1) % 狼和羊在北岸

            b = 0;

            return;

         end

         if(vi(3) == 1 && vi(4) == 1) % 羊和菜在北岸

            b = 0;

            return;

         end

   end


   v = vi-vj;

   d = sum(abs(v(2:4)));

 if(d > 1) % 这说明人带着两个或者以上的东西过河,这不符合最多携带一个的要求

      b = 0;

      return;

   end


   b = 1;

end



北太天元解人、狼、羊、菜渡河问题的评论 (共 条)

分享到微博请遵守国家法律