八皇后的C语言实现

来源:互联网 发布:centos 6.5改ssh端口 编辑:程序博客网 时间:2024/05/17 06:24
唯一的一门语言课Java课上老师讲过这个问题,使用“回退”的方法,期末考试也考过,但是这么多年来一直没有亲自去做过它,即使偶尔想到也觉得太过麻烦,没有那个能力实现。但是前两天一个兄弟作出来了,我觉得我也应该作出来,要不然实在没面子,于是使用C语言来实现一下。
一开始,我使用struct(A)来保存每一个皇后的位置,另外使用了一个struct(B)来保存当前列之前所有列中已放过皇后的位置,以防重复处理;我觉得方法思想上是没有问题的,但是运行的时候一个结果都没有出来,进入了死循环。我发现是往B中插入的数据没有成功,虽然在那个小funcion里边是没问题了,出来之后就回到原样了,因此已放过皇后的位置总是没有保存,每次都回退到之前的位置。
后来,我想到了另外一种实现,不使用struct,使用两个数组,分别保存每一列皇后的位置,已经皇后走过的标志(使用了2的row次方的方法,实际上跟前一个数组差不多),然后按照这个思路的结果,前边4个答案出来了,然后死循环,直到stack overflow。当我仔细分析算法的时候,我发现另一种更简洁一点的实现,只用一个数组,因为每一个数组元素储存的就是该列已经尝试过的最大值,下一次应该从它的下一个位置寻找。按照这个思路实现的结果跟上一个一样,只出来了4个答案(还差了88个)。
我再分析,发现是第一列第一个位置的所有可能情况找出来之后没法跳出循环,寻找第一列第二个位置的情况,于是我添加了
    if (i>=ROW && column==1)
        break;         /*45-46行*/   
如果第二列已经找到头了,就跳出。这个结果是得到了88个,看来最后一个位置(第一列)还有问题。于是我再添加了
    else if (column==0 && i>5)
        break;        /*47-48行*/
当回退到第一列的时候,第二列如果序号超过了5,就跳出,因为序号6和7是肯定无法匹配的。这样就没有问题了。
但是这样修改我觉得不够清晰明了,难解释,今早我想除了另外一个办法,在之后某个地方添加
    if (coulmn == 0)
        break;        /*73-74行*/
这是回退的时候如果退到第一列了,说明第一列当前位置已经搜索完毕,可以进入下一个位置了,根据实现,这里的循环就应该出来了。
具体的实现参看如下的源代码:

  1. /**
  2.  * Author: Hegc Huang
  3.  * Copyright 2008
  4.  */
  5. #include <stdio.h>
  6. #include <memory.h>

  7. #define ROW      8
  8. #define COLUMN   ROW

  9. int success = 0;    /*successful times*/

  10. void show(int* p)
  11. {
  12.     int i = 0;
  13.     printf("%2d>>> ", success);
  14.     for (i=0;i<COLUMN ; i++ )
  15.     {
  16.         printf("%d, ", p[i]);
  17.     }
  18.     printf("/n");
  19. }
  20. int main(int argc, char *argv[])
  21. {
  22.     int pieces[COLUMN];
  23.     int row      = 0;        /*row in the first column*/
  24.     int column   = 0;        /*the current column*/
  25.     int flag     = 0;        /*is matched in current column*/
  26.     int i        = 0;        /*row int current column*/
  27.     int j        = 0;        /*column from 0 to the one before the current column*/
  28.     int count    = 0;        /*steps need*/
  29.     /*set the pieces all as -1, [0,COLUMN) represents row in the n-th column*/
  30.     memset(pieces, -1, sizeof(pieces));
  31.     //init (0,0) as 0, and the current column add to the next column
  32.     pieces[column]     = 0;
  33.     column++;
  34.     
  35.     while (row < ROW)
  36.     {
  37.         while (column < COLUMN)
  38.         {
  39.             count++;
  40.             flag = 0;
  41.             i = pieces[column] + 1;
  42. //          if (i>=ROW && column==1)
  43. //              break;
  44. //          else if (column==0 && i>5)
  45. //              break;

  46.             for (i=i; i<ROW ;i++ )
  47.             {
  48.                 for (j=0 ;j<column ;j++ )
  49.                 {
  50.                     if (i==pieces[j] || abs(j-column)==abs(pieces[j]-i))
  51.                     {
  52.                         flag = 0;
  53.                         break;
  54.                     }
  55.                     flag = 1;
  56.                 }
  57.                 if (flag)
  58.                     break;
  59.             }
  60.             if (flag)
  61.             {
  62.                 pieces[column] = i;
  63.                 column++;
  64.             }
  65.             else
  66.             {
  67.                 pieces[column] = -1;
  68.                 column--;
  69.                 if (column == 0)  /*nowhere to go back*/
  70.                     break;
  71.             }
  72.         }/*internal while end*/
  73.         if (flag)
  74.         {
  75.             success++;
  76.             show(pieces);
  77.             flag = 0;
  78.             pieces[column-1]   = -1;
  79.             column   -= 2;
  80.         }
  81.         else
  82.         {
  83.             memset(pieces, -1, sizeof(pieces));
  84.             column = 0;
  85.             row++;
  86.             pieces[column] = row;
  87.             column++;
  88.         }
  89.     }/*external while end*/
  90.     printf("总共步数:%d/nPress Any Key to Continue.../n", count);
  91.     fflush(stdin);
  92.     getch();
  93.     return 0;
  94. }


当然,由于没有保存每次的结果的机制,所以每次完成之后都将结果打印出来,按照列的顺序,每一个数字是在列中的编号。
 1>>> 0, 4, 7, 5, 2, 6, 1, 3,
 2>>> 0, 5, 7, 2, 6, 3, 1, 4,
 3>>> 0, 6, 3, 5, 7, 1, 4, 2,
 4>>> 0, 6, 4, 7, 1, 3, 5, 2,
 5>>> 1, 3, 5, 7, 2, 0, 6, 4,
 6>>> 1, 4, 6, 0, 2, 7, 5, 3,
 7>>> 1, 4, 6, 3, 0, 7, 5, 2,
 8>>> 1, 5, 0, 6, 3, 7, 2, 4,
 9>>> 1, 5, 7, 2, 0, 3, 6, 4,
10>>> 1, 6, 2, 5, 7, 4, 0, 3,
11>>> 1, 6, 4, 7, 0, 3, 5, 2,
12>>> 1, 7, 5, 0, 2, 4, 6, 3,
13>>> 2, 0, 6, 4, 7, 1, 3, 5,
14>>> 2, 4, 1, 7, 0, 6, 3, 5,
15>>> 2, 4, 1, 7, 5, 3, 6, 0,
16>>> 2, 4, 6, 0, 3, 1, 7, 5,
17>>> 2, 4, 7, 3, 0, 6, 1, 5,
18>>> 2, 5, 1, 4, 7, 0, 6, 3,
19>>> 2, 5, 1, 6, 0, 3, 7, 4,
20>>> 2, 5, 1, 6, 4, 0, 7, 3,
21>>> 2, 5, 3, 0, 7, 4, 6, 1,
22>>> 2, 5, 3, 1, 7, 4, 6, 0,
23>>> 2, 5, 7, 0, 3, 6, 4, 1,
24>>> 2, 5, 7, 0, 4, 6, 1, 3,
25>>> 2, 5, 7, 1, 3, 0, 6, 4,
26>>> 2, 6, 1, 7, 4, 0, 3, 5,
27>>> 2, 6, 1, 7, 5, 3, 0, 4,
28>>> 2, 7, 3, 6, 0, 5, 1, 4,
29>>> 3, 0, 4, 7, 1, 6, 2, 5,
30>>> 3, 0, 4, 7, 5, 2, 6, 1,
31>>> 3, 1, 4, 7, 5, 0, 2, 6,
32>>> 3, 1, 6, 2, 5, 7, 0, 4,
33>>> 3, 1, 6, 2, 5, 7, 4, 0,
34>>> 3, 1, 6, 4, 0, 7, 5, 2,
35>>> 3, 1, 7, 4, 6, 0, 2, 5,
36>>> 3, 1, 7, 5, 0, 2, 4, 6,
37>>> 3, 5, 0, 4, 1, 7, 2, 6,
38>>> 3, 5, 7, 1, 6, 0, 2, 4,
39>>> 3, 5, 7, 2, 0, 6, 4, 1,
40>>> 3, 6, 0, 7, 4, 1, 5, 2,
41>>> 3, 6, 2, 7, 1, 4, 0, 5,
42>>> 3, 6, 4, 1, 5, 0, 2, 7,
43>>> 3, 6, 4, 2, 0, 5, 7, 1,
44>>> 3, 7, 0, 2, 5, 1, 6, 4,
45>>> 3, 7, 0, 4, 6, 1, 5, 2,
46>>> 3, 7, 4, 2, 0, 6, 1, 5,
47>>> 4, 0, 3, 5, 7, 1, 6, 2,
48>>> 4, 0, 7, 3, 1, 6, 2, 5,
49>>> 4, 0, 7, 5, 2, 6, 1, 3,
50>>> 4, 1, 3, 5, 7, 2, 0, 6,
51>>> 4, 1, 3, 6, 2, 7, 5, 0,
52>>> 4, 1, 5, 0, 6, 3, 7, 2,
53>>> 4, 1, 7, 0, 3, 6, 2, 5,
54>>> 4, 2, 0, 5, 7, 1, 3, 6,
55>>> 4, 2, 0, 6, 1, 7, 5, 3,
56>>> 4, 2, 7, 3, 6, 0, 5, 1,
57>>> 4, 6, 0, 2, 7, 5, 3, 1,
58>>> 4, 6, 0, 3, 1, 7, 5, 2,
59>>> 4, 6, 1, 3, 7, 0, 2, 5,
60>>> 4, 6, 1, 5, 2, 0, 3, 7,
61>>> 4, 6, 1, 5, 2, 0, 7, 3,
62>>> 4, 6, 3, 0, 2, 7, 5, 1,
63>>> 4, 7, 3, 0, 2, 5, 1, 6,
64>>> 4, 7, 3, 0, 6, 1, 5, 2,
65>>> 5, 0, 4, 1, 7, 2, 6, 3,
66>>> 5, 1, 6, 0, 2, 4, 7, 3,
67>>> 5, 1, 6, 0, 3, 7, 4, 2,
68>>> 5, 2, 0, 6, 4, 7, 1, 3,
69>>> 5, 2, 0, 7, 3, 1, 6, 4,
70>>> 5, 2, 0, 7, 4, 1, 3, 6,
71>>> 5, 2, 4, 6, 0, 3, 1, 7,
72>>> 5, 2, 4, 7, 0, 3, 1, 6,
73>>> 5, 2, 6, 1, 3, 7, 0, 4,
74>>> 5, 2, 6, 1, 7, 4, 0, 3,
75>>> 5, 2, 6, 3, 0, 7, 1, 4,
76>>> 5, 3, 0, 4, 7, 1, 6, 2,
77>>> 5, 3, 1, 7, 4, 6, 0, 2,
78>>> 5, 3, 6, 0, 2, 4, 1, 7,
79>>> 5, 3, 6, 0, 7, 1, 4, 2,
80>>> 5, 7, 1, 3, 0, 6, 4, 2,
81>>> 6, 0, 2, 7, 5, 3, 1, 4,
82>>> 6, 1, 3, 0, 7, 4, 2, 5,
83>>> 6, 1, 5, 2, 0, 3, 7, 4,
84>>> 6, 2, 0, 5, 7, 4, 1, 3,
85>>> 6, 2, 7, 1, 4, 0, 5, 3,
86>>> 6, 3, 1, 4, 7, 0, 2, 5,
87>>> 6, 3, 1, 7, 5, 0, 2, 4,
88>>> 6, 4, 2, 0, 5, 7, 1, 3,
89>>> 7, 1, 3, 0, 6, 4, 2, 5,
90>>> 7, 1, 4, 2, 0, 6, 3, 5,
91>>> 7, 2, 0, 5, 1, 4, 6, 3,
92>>> 7, 3, 0, 2, 5, 1, 6, 4,
总共步数:3920
Press Any Key to Continue...

原创粉丝点击