马踏棋盘----深度搜索、回溯

马踏棋盘问题(又称骑士周游或骑士漫游问题)是算法设计的经典问题之一。

 

国际象棋的棋盘为8*8的方格棋盘,现将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动。要求每个方格只能进入一次,最终使得“马”走遍棋盘64个方格。

编写代码,实现马踏棋盘的操作,要求用1~64来标注“马”移动的路径

对于在n*n的棋盘上,当n>=5且为偶数的时候,以任意点作点都有解。

回溯法:

思想很简单,就是一条路走到黑,碰壁了再回来一条路走到黑……一般和递归可以很好的搭配使用,还有深度优先搜索(DFS)。

实现代码

 

  1 /*===========================================================================*\
  2  *
  3  *                         马踏棋盘问题
  4  *
  5  *                      2013.06.01 by 樊列龙
  6  *
  7  *                        源码来自鱼C工作室
  8 \*===========================================================================*/
  9 
 10 #include <stdio.h>
 11 #include <time.h>
 12 
 13 #define X 8
 14 #define Y 8
 15 
 16 int chess[X][Y];
 17 
 18 //查找下一个位置
 19 int nextxy(int* x, int* y, int count)
 20 {
 21     switch(count)
 22     {
 23     case 0:
 24         if(*x + 2 <= X-1 && *y - 1 >= 0 && chess[*x+2][*y-1]==0)
 25         {
 26             *x += 2;
 27             *y -= 1;
 28             return 1;
 29         }
 30         break;
 31     case 1:
 32         if(*x + 2 <= X-1 && *y + 1 <= Y-1 && chess[*x+2][*y+1]==0)
 33         {
 34             *x += 2;
 35             *y += 1;
 36             return 1;
 37         }
 38         break;
 39     case 2:
 40         if(*x + 1 <= X-1 && *y - 2 >= 0 && chess[*x+1][*y-2]==0)
 41         {
 42             *x += 1;
 43             *y -= 2;
 44             return 1;
 45         }
 46         break;
 47     case 3:
 48         if(*x + 1 <= X-1 && *y + 2 <= Y - 1 && chess[*x+1][*y+2]==0)
 49         {
 50             *x += 1;
 51             *y += 2;
 52             return 1;
 53         }
 54         break;
 55     case 4:
 56         if(*x - 2 >= 0 && *y - 1 >= 0 && chess[*x-2][*y-1]==0)
 57         {
 58             *x -= 2;
 59             *y -= 1;
 60             return 1;
 61         }
 62         break;
 63     case 5:
 64         if(*x - 2 >= 0 && *y + 1 <= Y - 1 && chess[*x-2][*y+1]==0)
 65         {
 66             *x -= 2;
 67             *y += 1;
 68             return 1;
 69         }
 70         break;
 71     case 6:
 72         if(*x - 1 >= 0 && *y - 2 >= 0 && chess[*x-1][*y-2]==0)
 73         {
 74             *x -= 1;
 75             *y -= 2;
 76             return 1;
 77         }
 78         break;
 79     case 7:
 80         if(*x - 1 >= 0 && *y + 2 <= Y - 1 && chess[*x-1][*y+2]==0)
 81         {
 82             *x -= 1;
 83             *y += 2;
 84             return 1;
 85         }
 86         break;
 87 
 88     default:
 89         break;
 90     }
 91 
 92     return 0;
 93 }
 94 
 95 void print()
 96 {
 97     int i, j;
 98 
 99     for(i = 0; i < X; i++)
100     {
101         for(j = 0; j < Y; j++)
102         {
103             printf("%2d\t", chess[i][j]);
104         }
105         printf("\n");
106     }
107 
108     printf("\n");
109 }
110 
111 int TravlChessBord(int x, int y, int tag)
112 {
113     int x1 = x, y1 = y, count = 0, flag = 0;
114     chess[x][y] = tag;
115     if(X*Y == tag)
116     {
117         print();
118         return 1;
119     }
120     
121     //找下一个位置
122     flag = nextxy(&x1,&y1,count);
123     while(flag == 0 && count < 7)
124     {
125         count++;
126         flag = nextxy(&x1,&y1,count);
127     }
128 
129     while(flag)
130     {
131         printf("进入 <%d,%d>\n",x1,y1);
132         if(TravlChessBord(x1,y1,tag+1))
133         {
134             return 1;
135         }
136 
137         x1 = x;
138         y1 = y;
139         count++;
140 
141         flag = nextxy(&x1,&y1,count);
142         while(flag == 0 && count < 7)
143         {
144             count++;
145             flag = nextxy(&x1,&y1,count);
146         }
147     }
148 
149     if(0 == flag)
150     {
151         printf("退回... <%d,%d>)\n",x,y);
152         chess[x][y] = 0;
153     }
154 
155     return 0;
156 }
157 
158 int main()
159 {
160     int i, j;
161     clock_t start, finish;
162 
163     start = clock();
164     
165     for(i = 0; i < X; i++)
166     {
167         for(j = 0; j < Y; j++)
168         {
169            chess[i][j] = 0;
170         }
171     }
172 
173 
174     if(!TravlChessBord(0,0,1))
175     {
176         printf("抱歉马踏棋盘失败了!\n");
177     }
178     else
179     {
180         print();
181     }
182 
183     finish = clock();
184     
185 
186     printf("本次计算一共耗时 %f 秒\n\n",(double)(finish-start)/CLOCKS_PER_SEC);
187 
188     return 0;
189 }

 

测试结果:

当棋盘大于5的时候耗费的时间比较长,因此这里取5 X 5 的棋盘做测试:

  1 进入 <2,1>
  2 进入 <4,0>
  3 进入 <3,2>
  4 进入 <4,4>
  5 进入 <2,3>
  6 进入 <4,2>
  7 进入 <3,0>
  8 进入 <1,1>
  9 进入 <0,3>
 10 进入 <2,2>
 11 进入 <4,1>
 12 进入 <2,0>
 13 进入 <0,1>
 14 进入 <1,3>
 15 进入 <3,4>
 16 退回... <3,4>)
 17 退回... <1,3>)
 18 退回... <0,1>)
 19 进入 <1,2>
 20 进入 <3,1>
 21 进入 <4,3>
 22 进入 <2,4>
 23 退回... <2,4>)
 24 退回... <4,3>)
 25 进入 <1,0>
 26 进入 <0,2>
 27 进入 <1,4>
 28 进入 <3,3>
 29 退回... <3,3>)
 30 退回... <1,4>)
 31 退回... <0,2>)
 32 退回... <1,0>)
 33 退回... <3,1>)
 34 进入 <3,3>
 35 进入 <1,4>
 36 进入 <0,2>
 37 进入 <1,0>
 38 进入 <3,1>
 39 进入 <4,3>
 40 进入 <2,4>
 41 退回... <2,4>)
 42 退回... <4,3>)
 43 退回... <3,1>)
 44 退回... <1,0>)
 45 退回... <0,2>)
 46 退回... <1,4>)
 47 退回... <3,3>)
 48 进入 <2,4>
 49 进入 <4,3>
 50 进入 <3,1>
 51 进入 <1,0>
 52 进入 <0,2>
 53 进入 <1,4>
 54 进入 <3,3>
 55 退回... <3,3>)
 56 退回... <1,4>)
 57 退回... <0,2>)
 58 退回... <1,0>)
 59 退回... <3,1>)
 60 退回... <4,3>)
 61 退回... <2,4>)
 62 进入 <0,4>
 63 退回... <0,4>)
 64 退回... <1,2>)
 65 退回... <2,0>)
 66 进入 <3,3>
 67 进入 <1,2>
 68 进入 <3,1>
 69 进入 <4,3>
 70 进入 <2,4>
 71 退回... <2,4>)
 72 退回... <4,3>)
 73 进入 <1,0>
 74 进入 <0,2>
 75 进入 <1,4>
 76 退回... <1,4>)
 77 退回... <0,2>)
 78 退回... <1,0>)
 79 退回... <3,1>)
 80 进入 <2,0>
 81 进入 <0,1>
 82 进入 <1,3>
 83 进入 <3,4>
 84 退回... <3,4>)
 85 退回... <1,3>)
 86 退回... <0,1>)
 87 退回... <2,0>)
 88 进入 <2,4>
 89 进入 <4,3>
 90 进入 <3,1>
 91 进入 <1,0>
 92 进入 <0,2>
 93 进入 <1,4>
 94 退回... <1,4>)
 95 退回... <0,2>)
 96 退回... <1,0>)
 97 退回... <3,1>)
 98 退回... <4,3>)
 99 退回... <2,4>)
100 进入 <0,4>
101 退回... <0,4>)
102 退回... <1,2>)
103 进入 <1,4>
104 进入 <0,2>
105 进入 <1,0>
106 进入 <3,1>
107 进入 <4,3>
108 进入 <2,4>
109 进入 <1,2>
110 进入 <2,0>
111 进入 <0,1>
112 进入 <1,3>
113 进入 <3,4>
114 退回... <3,4>)
115 退回... <1,3>)
116 退回... <0,1>)
117 退回... <2,0>)
118 进入 <0,4>
119 退回... <0,4>)
120 退回... <1,2>)
121 退回... <2,4>)
122 退回... <4,3>)
123 进入 <1,2>
124 进入 <2,0>
125 进入 <0,1>
126 进入 <1,3>
127 进入 <3,4>
128 退回... <3,4>)
129 退回... <1,3>)
130 退回... <0,1>)
131 退回... <2,0>)
132 进入 <2,4>
133 进入 <4,3>
134 退回... <4,3>)
135 退回... <2,4>)
136 进入 <0,4>
137 退回... <0,4>)
138 退回... <1,2>)
139 退回... <3,1>)
140 退回... <1,0>)
141 退回... <0,2>)
142 退回... <1,4>)
143 退回... <3,3>)
144 退回... <4,1>)
145 进入 <4,3>
146 进入 <2,4>
147 进入 <1,2>
148 进入 <3,1>
149 进入 <1,0>
150 进入 <0,2>
151 进入 <1,4>
152 进入 <3,3>
153 进入 <4,1>
154 进入 <2,0>
155 进入 <0,1>
156 进入 <1,3>
157 进入 <3,4>
158 退回... <3,4>)
159 退回... <1,3>)
160 退回... <0,1>)
161 退回... <2,0>)
162 退回... <4,1>)
163 退回... <3,3>)
164 退回... <1,4>)
165 退回... <0,2>)
166 退回... <1,0>)
167 退回... <3,1>)
168 进入 <3,3>
169 进入 <4,1>
170 进入 <2,0>
171 进入 <0,1>
172 进入 <1,3>
173 进入 <3,4>
174 退回... <3,4>)
175 退回... <1,3>)
176 退回... <0,1>)
177 退回... <2,0>)
178 退回... <4,1>)
179 进入 <1,4>
180 进入 <0,2>
181 进入 <1,0>
182 进入 <3,1>
183 退回... <3,1>)
184 退回... <1,0>)
185 退回... <0,2>)
186 退回... <1,4>)
187 退回... <3,3>)
188 进入 <2,0>
189 进入 <4,1>
190 进入 <3,3>
191 进入 <1,4>
192 进入 <0,2>
193 进入 <1,0>
194 进入 <3,1>
195 退回... <3,1>)
196 退回... <1,0>)
197 退回... <0,2>)
198 退回... <1,4>)
199 退回... <3,3>)
200 退回... <4,1>)
201 进入 <0,1>
202 进入 <1,3>
203 进入 <3,4>
204 退回... <3,4>)
205 退回... <1,3>)
206 退回... <0,1>)
207 退回... <2,0>)
208 进入 <0,4>
209 退回... <0,4>)
210 退回... <1,2>)
211 退回... <2,4>)
212 进入 <3,1>
213 进入 <1,0>
214 进入 <0,2>
215 进入 <1,4>
216 进入 <3,3>
217 进入 <4,1>
218 进入 <2,0>
219 进入 <0,1>
220 进入 <1,3>
221 进入 <3,4>
222 退回... <3,4>)
223 退回... <1,3>)
224 退回... <0,1>)
225 进入 <1,2>
226 进入 <2,4>
227 退回... <2,4>)
228 进入 <0,4>
229 退回... <0,4>)
230 退回... <1,2>)
231 退回... <2,0>)
232 退回... <4,1>)
233 进入 <1,2>
234 进入 <2,0>
235 进入 <4,1>
236 退回... <4,1>)
237 进入 <0,1>
238 进入 <1,3>
239 进入 <3,4>
240 退回... <3,4>)
241 退回... <1,3>)
242 退回... <0,1>)
243 退回... <2,0>)
244 进入 <2,4>
245 退回... <2,4>)
246 进入 <0,4>
247 退回... <0,4>)
248 退回... <1,2>)
249 退回... <3,3>)
250 退回... <1,4>)
251 退回... <0,2>)
252 退回... <1,0>)
253 进入 <1,2>
254 进入 <3,3>
255 进入 <4,1>
256 进入 <2,0>
257 进入 <0,1>
258 进入 <1,3>
259 进入 <3,4>
260 退回... <3,4>)
261 退回... <1,3>)
262 退回... <0,1>)
263 退回... <2,0>)
264 退回... <4,1>)
265 进入 <1,4>
266 进入 <0,2>
267 进入 <1,0>
268 退回... <1,0>)
269 退回... <0,2>)
270 退回... <1,4>)
271 退回... <3,3>)
272 进入 <2,0>
273 进入 <4,1>
274 进入 <3,3>
275 进入 <1,4>
276 进入 <0,2>
277 进入 <1,0>
278 退回... <1,0>)
279 退回... <0,2>)
280 退回... <1,4>)
281 退回... <3,3>)
282 退回... <4,1>)
283 进入 <0,1>
284 进入 <1,3>
285 进入 <3,4>
286 退回... <3,4>)
287 退回... <1,3>)
288 退回... <0,1>)
289 退回... <2,0>)
290 进入 <2,4>
291 退回... <2,4>)
292 进入 <0,4>
293 退回... <0,4>)
294 退回... <1,2>)
295 退回... <3,1>)
296 退回... <4,3>)
297 进入 <3,4>
298 进入 <1,3>
299 进入 <0,1>
300 进入 <2,0>
301 进入 <4,1>
302 进入 <3,3>
303 进入 <1,2>
304 进入 <3,1>
305 进入 <4,3>
306 进入 <2,4>
307 退回... <2,4>)
308 退回... <4,3>)
309 进入 <1,0>
310 进入 <0,2>
311 进入 <1,4>
312 退回... <1,4>)
313 退回... <0,2>)
314 退回... <1,0>)
315 退回... <3,1>)
316 进入 <2,4>
317 进入 <4,3>
318 进入 <3,1>
319 进入 <1,0>
320 进入 <0,2>
321 进入 <1,4>
322 退回... <1,4>)
323 退回... <0,2>)
324 退回... <1,0>)
325 退回... <3,1>)
326 退回... <4,3>)
327 退回... <2,4>)
328 进入 <0,4>
329 退回... <0,4>)
330 退回... <1,2>)
331 进入 <1,4>
332 进入 <0,2>
333 进入 <1,0>
334 进入 <3,1>
335 进入 <4,3>
336 进入 <2,4>
337 进入 <1,2>
338 进入 <0,4>
339  1      14      19      10      25
340 20       9      24      13      18
341 15       2      11       6      23
342  8      21       4      17      12
343  3      16       7      22       5
344 
345 本次计算一共耗时 1.019000
View Code

 

posted @ 2013-06-01 03:47  Cocoon  阅读(912)  评论(0编辑  收藏  举报