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郵箱
