數據結構設計——農夫過河問題


本篇文章中所有數據結構都是后期整理的,如有問題歡迎指正,轉載請注明出處http://www.cnblogs.com/a1982467767/p/8889683.html

農夫過河問題

 

1、 問題描述:

 

設有一個農夫帶一只狼,一只羊和一筐菜來到河邊,打算乘一只船從右岸渡到左岸去.該船的負載能力為農夫每次只能帶一樣東西過河.在無農夫的時候,狼和羊不能在一起,羊和菜不能在一起.設計一個方案,使農夫可以無損失地渡過河.

 

2、 設計思路:

 

設計好圖的結構,點以(農夫,狼,羊,菜)表示,設置圖的點集,邊集,點數,邊數;

 

is_safe函數確定圖中各點是否安全,將不安全的點去掉,剩下安全的點,然后判斷兩點之間是否可變換,再通過層次遍歷找到路徑,設定好參數,打印出路徑;

 

3、 代碼實現

 

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<windows.h>
  4 #define MaxVertexNum 16
  5 
  6 typedef struct{ 
  7     int farmer;
  8     int wolf;
  9     int sheep;
 10     int vegetable;
 11 }VertexType;//四元組
 12 
 13 typedef struct{
 14     VertexType vertexs[MaxVertexNum];//頂點表表示點集
 15     int edges[MaxVertexNum][MaxVertexNum];//以鄰接矩陣表示邊集
 16     int vertexNum, edgeNum;//點數,邊數
 17 }MGraph;//是以鄰接矩陣存儲的圖類型
 18 
 19 typedef enum{False,Ture} Boolean;
 20 
 21 Boolean visited[MaxVertexNum];//對已經訪問的點進行標記
 22 int path[MaxVertexNum];//保存DFS搜索的路徑,即某頂點到下一個頂點的路徑
 23 
 24 int Locate(MGraph * G, int F, int W, int S, int V)
 25 {
 26     //查找頂點(F,W,S,V)在頂點向量中的位置
 27     int i;
 28     for (i = 0; i < G->vertexNum; i++)
 29         if (G->vertexs[i].farmer == F &&  G->vertexs[i].wolf == W &&
 30             G->vertexs[i].sheep == S && G->vertexs[i].vegetable == V)
 31             return (i);//返回當前位置
 32     return -1;//沒有查找到此頂點
 33 }
 34 int Is_safe(int F, int W, int S, int V)
 35 {//當農夫與羊不在一起時,狼和羊 或 羊和白菜在一起是不安全的
 36     if (F != S && (W == S || S == V)) return 0;
 37     else return 1;//否則返回安全
 38 }
 39 
 40 //狀態是否可轉換,條件是農夫狀態不同,物品至多一項不同
 41 int Is_connected(MGraph *G, int i, int j)
 42 {//判斷i和j的狀態是否可以轉換
 43     int k = 0;
 44     if (G->vertexs[i].wolf != G->vertexs[j].wolf) k++;
 45     if (G->vertexs[i].sheep != G->vertexs[j].sheep) k++;
 46     if (G->vertexs[i].vegetable != G->vertexs[j].vegetable) k++;
 47     if (G->vertexs[i].farmer != G->vertexs[j].farmer && k <= 1)
 48         //以上三個條件不同時滿足且農夫狀態改變時,返回真,即農夫每次只能帶一件東西過河
 49         return 1;
 50     else return 0;
 51 }
 52 
 53 void  CreateG(MGraph *G)
 54 {
 55     int i, j, F, W, S, V;
 56     i = 0;
 57     for (F = 0; F <= 1; F++)           //通過安全監測函數,生成所有安全圖的頂點
 58         for (W = 0; W <= 1; W++)
 59             for (S = 0; S <= 1;S++)
 60                 for (V = 0; V <= 1;V++)
 61                     if (Is_safe(F, W, S, V))
 62                     {
 63                         G->vertexs[i].farmer = F;
 64                         G->vertexs[i].wolf = W;
 65                         G->vertexs[i].sheep = S;
 66                         G->vertexs[i].vegetable = V;
 67                         i++;
 68                     }
 69     G->vertexNum = i;//安全點數
 70     for (i = 0; i < G->vertexNum; i++)
 71         for (j = 0; j < G->vertexNum; j++)
 72             if (Is_connected(G, i, j))//狀態i與狀態j之間可轉化,初始值為1,否則為0
 73                 G->edges[i][j] = G->edges[j][i] = 1;
 74             else
 75                 G->edges[i][j] = G->edges[j][i] = 0;
 76     return;
 77 }
 78 void Print_Path(MGraph *G, int u, int v)
 79 //輸出從u到v的簡單路徑,即頂點序列中不重復出現的路徑
 80 {
 81     int    k;
 82     k = u;
 83     printf("顯示右岸已經過河的物體(農夫,狼,羊,菜)\n");
 84     while (k != v)//可達的情況下,以狀態是否相同為依據,打印到達前的所有狀態
 85     {
 86         printf("(%d,%d,%d,%d)\n", G->vertexs[k].farmer, G->vertexs[k].wolf,
 87             G->vertexs[k].sheep, G->vertexs[k].vegetable);
 88         k = path[k];
 89     }
 90     //打印到達的狀態
 91     printf("(%d,%d,%d,%d)\n", G->vertexs[k].farmer, G->vertexs[k].wolf,
 92         G->vertexs[k].sheep, G->vertexs[k].vegetable);
 93 }
 94 
 95 void Print_Graph(MGraph *G, int u, int v)
 96 {//輸出從u到v的簡單可視
 97     int    k;
 98     k = u;
 99     while (k != v)
100     {    
101         Sleep(1500);
102         system("cls");
103         printf("左岸 ||        || 右岸\n");
104         printf("-----++--------++-----\n");
105         if (G->vertexs[k].farmer == 0)    printf("農夫 ||        || \n");
106         else printf("     ||        || 農夫\n");
107         if (G->vertexs[k].wolf == 0)    printf(" 狼  ||   河   || \n");
108         else printf("     ||   河   ||  狼\n");
109         if (G->vertexs[k].sheep == 0)    printf(" 羊  ||        || \n");
110         else printf("     ||        ||  羊\n");
111         if (G->vertexs[k].vegetable == 0)    printf("蔬菜 ||        || \n");
112         else printf("     ||        || 蔬菜\n");
113         k = path[k];    
114     }
115     Sleep(1500);
116     system("cls");    
117     printf("左岸 ||        || 右岸\n");
118     printf("-----++--------++-----\n");
119     printf("     ||        || 農夫\n");
120     printf("     ||   河   ||  狼\n");
121     printf("     ||        ||  羊\n");
122     printf("     ||        || 蔬菜\n");
123     printf("農夫的物品已安全過河...\n");
124 }
125 void DFS_path(MGraph *G, int u, int v)
126 //深度優先搜索從u到v的簡單路徑
127 {
128     int j;
129     visited[u] = Ture;//標志已訪問的頂點,即1
130     for (j = 0; j < G->vertexNum;j++)
131         if (G->edges[u][j] && !visited[j] && !visited[v])
132         {
133             //鄰接矩陣中存在u、j兩點的路徑,且j、v沒有被訪問
134             path[u] = j;
135             DFS_path(G, j, v);
136         }
137 }
138 int main()
139 {
140     int i, j;
141     MGraph graph;
142     CreateG(&graph);
143     for (i = 0; i < graph.edgeNum; i++)   visited[i] = False;//0表示沒有訪問,即置初值
144     i = Locate(&graph, 0, 0, 0, 0);//定位i在圖存儲中的位置
145     j = Locate(&graph, 1, 1, 1, 1);//定位j在圖存儲中的位置
146     DFS_path(&graph, i, j);
147     if (visited[j])
148     {
149         Print_Path(&graph, i, j);
150         printf("1.5秒后打印路徑...\n");
151         Print_Graph(&graph, i, j);
152 
153     }
154     system("pause");
155     return 0;
156 }

1、 實驗結果:

 

........

 

 

5、  心得體會:

通過兩周的課程設計,我學會了如何寫一個精簡、快速、健壯的程序。一個好的程序應該是一個所占空間小、運行時間短、其他性能也好的程序。而要做出一個好的程序則應該通過對算法與其數據結構的時間復雜度和空間復雜度進行實現與改進。然而,實際上很難做到十全十美,原因是各要求有時相互抵觸,要節約算法的執行時間往往要以犧牲更多的存儲空間為代價:而為了節省存儲空間又可能要以更多的時間為代價。因此,只能根據具體情況有所側重:如果程序的使用次數較少,則應該力求算法簡明易懂,而易於轉換為上機程序;如果程序反復多次使用,則應該盡可能選用快速算法;如果解決問題的數據量極大,機器的內存空間較小,則在編寫算法時應該考慮如何節省空間。  本次課程設計培養了了我們獨立思考的能力,提高了我們的動手操作水平。在具體設計操作中,我們鞏固了本學期所學的數據結構與算法的理論知識,進一步提高了自己的編程能力。這也是課程設計的最終目的所在。通過實際操作,開發了自己的邏輯思維能力,培養了分析問題、解決問題的能力。  但在程序設計的過程中我也深刻的感受到自己實力的不足,無法靈活的運用各種工具和函數,對於課程所講的東西也無法在脫離課本的情況中完成,我意識到自己在今后的學習生活中,一定要勤於思考,扎實掌握理論知識,靈活運用課上所學的東西,做一個優秀的程序員。

 

 

 

 

 

 


免責聲明!

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



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