clc; clear; global State; %此程序计算传教士与野人问题: %三个传教士与三个野人分别站在河的两岸,有一条船,可以载一至两人。要求用船载人,把三个传教士、野人载过岸,要求每个地方的野人数量不能大于传教士 % 初始状态: % 'Fa1' ' ' 'Sa1' % 'Fa2' ' ' 'Sa2' % 'Fa3' 'Sa3' % % 最终状态 % 'Sa1' ' ' 'Fa1' % 'Sa2' ' ' 'Fa2' % 'Sa3' 'Fa3' %定义初始状态 %河的左岸为3个传教士,0个野人 %河的右岸为0个传教士,3个野人 State_Begin = { 'Fa' , 'Fa', 'Fa' 'Sa', 'Sa', 'Sa' 'none','none'}; %最终状态 %河的左岸为0个传教士,3个野人 %河的右岸为3个传教士,0个野人 %State_Final = { 'Sa', 'Sa', 'Sa' 'Fa' , 'Fa', 'Fa' 'none', 'none'}; %生成State的序列,结果就是State_Begin -> State1 -> State2 -> State3 -> .....->State_Final %构建状态点,包含当前节点编号(No_now), 父节点编号(No_dad),f,g,是否已被展开过(1为展开过,0为未展开),当前状态(8个状态变量) %初始状态 State ={'No_now','No_dad','f','g','Flag','State_L1','State_L2','State_L3','State_R1','State_R2','State_R3','State_B1','State_B2'}; g=1; h= fun_h(State_Begin); f= h + g; Flag = 0; %未被展开 State =[State ;[1,1,f,g,Flag,State_Begin]]; while h~=0 %展开结点,并将展开的节点状态从后面加入State ind = find(cell2mat(State(2:end,5))==0); %找到没有被展开的接点 %由没展开的接点组成新的State State_new = State(ind+1 , :); fmin = min(cell2mat(State_new(:,3))); ind_new = find(cell2mat(State_new(:,3)) == fmin); if length(ind_new)==1 No_now_tmp = ind_new; else No_now_tmp = ind_new(1); end No_now = State_new{No_now_tmp,1}; fun_unfold(No_now); %判断是否获得了终点状态 mat_h = cell2mat(State(2:end,3)) - cell2mat(State(2:end,4)); indh = find(mat_h == 0); if isempty(indh)==1 h = 1; else h = 0; end end % %显示结果 % 数据格式为{'No_now','No_dad','f','g','Flag','State_L1','State_L2','State_L3','State_R1','State_R2','State_R3','State_B1','State_B2'} mat_h = cell2mat(State(2:end,3)) -cell2mat(State(2:end,4)); ind = find( mat_h == 0 ); if length(ind)==1 No_now_tmp = ind; else No_now_tmp = ind(1); end No_now = State{No_now_tmp+1,1}; disp(State(No_now_tmp+1,6:end)); while No_now ~= 1 No_now = State{No_now+1,2}; ind = find(cell2mat(State(2:end,1)) == No_now ); disp(' /\ /\ '); disp(' | | '); disp(State(ind+1,6:end)); end
function fun_unfold(No_now) global State; %数据格式为{'No_now','No_dad','f','g','Flag','State_L1','State_L2','State_L3','State_R1','State_R2','State_R3','State_B1','State_B2'} State_unfold = State(No_now+1,:); %每展开一次,层数就相对上层增加1层 g= State_unfold{4} + 1; for i=6:11 for j=6:11 State_tmp = State_unfold; tmp = State_tmp{i}; State_tmp{i} = State_tmp{12}; State_tmp{12} = tmp; tmp = State_tmp{j}; State_tmp{j} = State_tmp{13}; State_tmp{13} = tmp; check = fun_check(State_tmp(6:13)); if check == 1 f = fun_h(State_tmp(6:13)) + g; State_tmp{3} = f; State_tmp{4} = g; State_tmp{2} = No_now ; % 父节点即为No_now 结点 [r,~] = size(State); State_tmp{1} = r; State = [State ; State_tmp]; end end end State{No_now+1,5} = 1; end
function [check]=fun_check(State_now) %分别统计两岸的野人数和神父数,要求野人数不要大于神父数,否则返回0 %左岸检查 Fa1=0; Sa1=0; check1 = 0; check2 = 0; for i=1:3 if strcmp(State_now{i},'Fa')==1 Fa1 = Fa1+1; elseif strcmp(State_now{i},'Sa')==1 Sa1 = Sa1+1; end end if (Fa1 ~= 0) && (Sa1 >Fa1) check = 0; else check1 = 1; end %右岸检查 Fa2=0; Sa2=0; for i=4:6 if strcmp(State_now{i},'Fa')==1 Fa2 = Fa2+1; elseif strcmp(State_now{i},'Sa')==1 Sa2 = Sa2+1; end end if (Fa2 ~= 0) && (Sa2 >Fa2) check = 0; else check2 = 1; end if check2 == 1 && check1 ==1 check =1; else check =0; end end
function h = fun_h (state) %%h为从当前状态到目标状态的代价 %最终状态 %河的左岸为0个传教士,3个野人 %河的右岸为3个传教士,0个野人 %State_Final = { 'Sa', 'Sa', 'Sa' 'Fa' , 'Fa', 'Fa' 'none', 'none'}; h = 0; for i=1:3 if strcmp(state{i},'Sa')~=1 h = h + 1; end end for i=4:6 if strcmp(state{i},'Fa')~=1 h = h + 1; end end end
版权保留,不对以上代码负责
交流请联系huiweis的gmail邮箱
Matlab源代码,版权保留,不对以上代码负责。交流请联系huiweis的gmail邮箱