3傳教士與3野人過河問題的A*算法


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM