野人和傳教士過河問題的C語言源代碼

  1 //問題:有3個傳教士和3個野人要過河,只有一艘船,這艘船每次
  2 //只能載2個人過河,且無論哪邊野人的數量大於傳教士的數量時,
  3 //野人就會吃掉傳教士。怎樣讓他們都安全過河?
  4 
  5 #include <stdio.h>
  6 #include <string.h>
  7 
  8 #define STEP_MAX 20 //來回過河的次數
  9 #define KIND_NUM 3 //每個種類的數量
 10 #define BOAT_NUM 2 //船的載重量
 11 
 12 typedef enum
 13 {
 14     BOAT_THIS,//船在本岸
 15     BOAT_THAT,//船在對岸
 16 } boat_t;
 17 
 18 typedef enum
 19 {
 20     ROAD_GO,//過河
 21     ROAD_COME,//回來
 22 } road_t;
 23 
 24 typedef struct
 25 {
 26     int ye;//對岸野人數量
 27     int man;//對岸傳教士數量
 28     boat_t boat;//船是否在對岸
 29 } state_t;//一種局面
 30 
 31 typedef struct
 32 {
 33     int ye;//野人過河數量
 34     int man;//傳教士過河的數量
 35     road_t road;//回來或過河
 36 } step_t;//一個步驟
 37 
 38 
 39 state_t states[STEP_MAX] = { 0 };
 40 step_t steps[STEP_MAX] = { 0 };
 41 
 42 
 43 //判斷所有的野人和傳教士是否都到了對岸
 44 bool final(state_t s)
 45 {
 46     const state_t cs =
 47     {
 48        KIND_NUM,
 49        KIND_NUM,
 50        BOAT_THAT
 51     };
 52     if (memcmp(&cs, &s, sizeof(state_t)) == 0)
 53     {
 54         return true;
 55     }
 56     return false;
 57 }
 58 
 59 //是否會發生野人殺傳教士
 60 bool bad(state_t s)
 61 {
 62     if (((KIND_NUM - s.ye) > (KIND_NUM - s.man) 
 63         && (KIND_NUM - s.man) > 0)
 64         || (s.ye > s.man&& s.man > 0))
 65     {
 66         return true;
 67     }
 68     return false;
 69 }
 70 
 71 //第n種局面是否跟前面的相重複
 72 bool repeat(state_t s[], int n)
 73 {
 74     int i;
 75 
 76     for (i = 0; i < n; i++)
 77     {//已經有這種情況了
 78         if (memcmp(&states[i], &states[n], sizeof(states[i])) == 0)
 79         {
 80             return true;
 81         }
 82     }
 83     return false;
 84 }
 85 
 86 void output(step_t steps[STEP_MAX], int n)
 87 {
 88     const char* kinds[KIND_NUM] = { "野人","傳教士" };
 89     const char* roads[2] = { "過河.","回來." };
 90     int i;
 91 
 92     for (i = 0; i < n; i++)
 93     {
 94         if ((steps[i].ye * steps[i].man) > 0)
 95         {
 96             printf("%d個%s和%d個%s%s\n", steps[i].ye, kinds[0],
 97                 steps[i].man, kinds[1], roads[steps[i].road]);
 98         }
 99         else if (steps[i].ye > 0)
100         {
101             printf("%d個%s%s\n", steps[i].ye, kinds[0],
102                 roads[steps[i].road]);
103         }
104         else if (steps[i].man > 0)
105         {
106             printf("%d個%s%s\n", steps[i].man, kinds[1],
107                 roads[steps[i].road]);
108         }
109     }
110     printf("\n");
111 }
112 
113 //搜索過河方案(n表示過河次數)
114 void search(int n)
115 {
116     int i, j;
117 
118     if (n > STEP_MAX)
119     {//步數限制太少了
120         printf("Step Overflow!");
121         return;
122     }
123     if (final(states[n]))
124     {//都到對岸了
125         output(steps, n);
126         return;
127     }
128     if (bad(states[n]))
129     {//發生了野人殺傳教士了
130         return;
131     }
132     if (repeat(states, n))
133     {//與前面的局面相重複了
134         return;
135     }
136     if (states[n].boat == BOAT_THIS)
137     {//船在本岸
138         for (i = 0; i <= BOAT_NUM && i <= (KIND_NUM - states[n].ye); i++)
139             for (j = 0; j <= BOAT_NUM - i && j <= (KIND_NUM - states[n].man); j++)
140             {
141                 if (i == 0 && j == 0)
142                 {
143                     continue;
144                 }
145                 steps[n].ye = i;
146                 steps[n].man = j;
147                 steps[n].road = ROAD_GO;
148                 memcpy(&states[n + 1], &states[n], sizeof(state_t));
149                 states[n + 1].ye += i;
150                 states[n + 1].man += j;
151                 states[n + 1].boat = BOAT_THAT;
152                 search(n + 1);
153             }
154     }
155     else
156     {
157         for (i = 0; i <= BOAT_NUM && i <= states[n].ye; i++)
158         {
159             for (j = 0; j <= BOAT_NUM - i && j <= states[n].man; j++)
160             {
161                 if (i == 0 && j == 0)
162                 {
163                     continue;
164                 }
165                 steps[n].ye = i;
166                 steps[n].man = j;
167                 steps[n].road = ROAD_COME;
168                 memcpy(&states[n + 1], &states[n], sizeof(state_t));
169                 states[n + 1].ye -= i;
170                 states[n + 1].man -= j;
171                 states[n + 1].boat = BOAT_THIS;
172                 search(n + 1);
173             }
174         }
175     }
176 }
177 
178 int main()
179 {
180     search(0);
181     return 0;
182 }

1個野人和1個傳教士過河.
1個傳教士回來.
2個野人過河.
1個野人回來.
2個傳教士過河.
1個野人和1個傳教士回來.
2個傳教士過河.
1個野人回來.
2個野人過河.
1個傳教士回來.
1個野人和1個傳教士過河.

1個野人和1個傳教士過河.
1個傳教士回來.
2個野人過河.
1個野人回來.
2個傳教士過河.
1個野人和1個傳教士回來.
2個傳教士過河.
1個野人回來.
2個野人過河.
1個野人回來.
2個野人過河.

2個野人過河.
1個野人回來.
2個野人過河.
1個野人回來.
2個傳教士過河.
1個野人和1個傳教士回來.
2個傳教士過河.
1個野人回來.
2個野人過河.
1個傳教士回來.
1個野人和1個傳教士過河.

2個野人過河.
1個野人回來.
2個野人過河.
1個野人回來.
2個傳教士過河.
1個野人和1個傳教士回來.
2個傳教士過河.
1個野人回來.
2個野人過河.
1個野人回來.
2個野人過河.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章