求解農夫過河問題

2021-08-26 14:52:16 字數 2354 閱讀 2871

問題:乙個農夫帶著一匹狼、乙隻羊、一顆白菜要過河,只有一條船而且農夫每次最多只能帶乙個動物或物品過河,並且當農夫不在的時候狼會吃羊,羊會吃白菜,列出所有安全將所有動物和物品帶過河的方案。

思路分析:顯然這不是乙個最優解的問題,最容易想到的方法就是遍歷了,設法用遍歷列舉出所有可能出現的情況,根據條件選取出其中所有正確的解路徑。把每個狀態看作乙個節點的話,那麼節點的子節點可以設計為4個,分別對應的情況是:農夫單獨過河、農夫帶狼過河、農夫帶羊過河、農夫帶白菜過河,則所有的情況頂多構成一棵滿4叉樹。因為其中有的狀態是不合法的,可以通過約束進行裁剪,實際這棵4叉樹會小得多。問題解的模型就確定下來了,接下來是需要用一種搜尋方法找到樹中所有合法的解路徑,我用的是深度優先搜尋對這棵4叉樹進行路徑搜尋,當搜尋到的節點為最終目標節點時,那麼從起始節點到該目標節點經過的路徑就是乙個解路徑,直到搜尋完這棵樹後就能找到所有的解路徑了。

tips:

1、為了程式能夠便於表示,狀態可以用4位二進位制數來表示,0000(int型別為0)代表初始狀態,從左往右每一位依次表示農夫、狼、羊、白菜,0表示在起始岸,1代表在目的岸,則目標狀態為1111(int型別為15)。故用整型0-15這16個數字就可以表示所有狀態了。

2、當程式進行深度優先搜尋時,需要記錄下該路徑經過的節點(狀態),因為節點(狀態)是不能重複的,重複的情況沒有意義,比如開始農夫把羊帶到對岸,然後又把羊帶回來,則此時重複了起始狀態這就沒有任何意義,而且也會讓程式無限迴圈。所以用乙個int route[16]陣列就可以記錄任何一條路徑(因為一條路徑頂多佔滿所有16個狀態),陣列的下標就表示該狀態,陣列的內容就記錄上乙個節點(狀態)即其下標,比如route[15]=5表示節點(狀態)15(即目標狀態1111)上乙個節點(狀態)是5(即0101),再翻譯白一點就是最後一步為農夫帶羊過河(0101至1111)。

c語言**:

#include

int famerlocation(int currentlocation) //判斷農民的位置

else

}int wolflocation(int currentlocaiton) //判斷狼的位置

else

}int goatlocation(int currentlocation) //判斷羊的位置

else

}int cabbagelocation(int currentlocation) //判斷白菜的位置

else

}int judgesafe(int currentlocation) //判斷當前狀態是否安全

else

if((a!=c)&&(c==d)) //當農夫和羊位置不同而羊和白菜位置相同時不安全

else

}void printroute(int route[16]) //根據乙個路徑陣列輸出一條路徑

printf("\n");

}void process(int route[16],int currentlocation) //演算法核心,輸入要處理的路徑route[16]和該路徑當前最新位置currentlocation

nextroute[nextlocation]=currentlocation; //然後再記錄下這新的一步

process(nextroute,nextlocation); //用遞迴(深度優先搜尋)再以同樣方式處理這個新的路徑和最新位置

}} }}

else

//該路徑到達了目標狀態

}int main()

route[0]=-2; //起始狀態已經經歷過且沒有前驅節點記錄為-2

process(route,0); //處理該條起始路徑即可

}

程式執行結果:

15 5 13 1 11 2 10 0

15 5 13 4 14 2 10 0

找到2個安全的方案,把它翻譯過來就是:

1、0(0000)—(農夫帶羊過河)—10(1010)—(農夫單獨返回)—2(0010)—(農夫帶白菜過河)—11(1011)—(農夫帶羊返回)—1(0001)—(農夫帶狼過河)—13(1101)—(農夫單獨返回)—5(0101)—(農夫帶羊過河)—15(1111)

1、0(0000)—(農夫帶羊過河)—10(1010)—(農夫單獨返回)—2(0010)—(農夫帶狼過河)—14(1110)—(農夫帶羊返回)—4(0100)—(農夫帶白菜過河)—13(1101)—(農夫單獨返回)—5(0101)—(農夫帶羊過河)—15(1111)

農夫過河問題

題目描述 有乙個農夫帶乙隻羊 一筐菜和乙隻狼過河。如果沒有農夫看管,則狼要吃羊,羊要吃菜。但是船很小,只夠農夫帶一樣東西過河。問農夫該如何解此難題?我的 include include include include include include include using namespace s...

農夫過河問題

問題 有一人帶著狼羊菜來到河的左岸欲乘乙隻小船過到右岸,每次人只能帶其中乙個過河 當有人在不會有事 當無人在時 就不允 許狼和羊在一起,也不允許羊和菜在一起,設計演算法以最少的次數過河?採用位向量,4個二進位制位的0 1情況表示狀態,顯而易見,共24 16種可能狀態。從高位到低位分別表示農夫 狼 白...

C 農夫過河問題

農夫過河問題 大家有沒有看過我的c學習中的位算,我們用8位二進位制的數字來表示任務的完成與否,1完成 0未完成 現在我們用4個二進位制數來代表 第一位表示農夫 1 北岸,0 南岸 第二位表示狼 1 北岸,0 南岸 第三位表示?1 北岸,0 南岸 第四位表示白菜 1 北岸,0 南岸 我們怎麼判斷農夫在...