C语言学习--八皇后问题

问题描述:

在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

程序设计:

1、一维数组a[17],数组分成三段,第一段a[0]用来标记八皇后安置完成;第二段a[1,8]用来标记列位置有无子,方便判断列冲突;第三段a[9,16]用来标记存储位置。

2、关键算法 递归判断位置,eightQueens 。

3、对角线位置互斥判断, isDiagonal。

4、输出函数, printResult。

算法描述:

1、首次传入为数组a和起始列变量i=1,判断标记为a[0]是否为1,为1进入2,否则进入3;

2、打印数组a[9,16];

3、测试j是否小于8,下于则递归结束,否则探测j列是否合法,合法进入4,否则j++,重走3;

4、列标记为a[j]置1,存储位置标记a[8+i]置为i,j组合的位置代号(i*10+j);

5、判断是否已安置所有皇后,是则将标记为a[0]置1。

6、列号加1,再次递归。

7、清除本次递归设置的值,为方便回溯、重新寻找其他组合的,返回3。

  1 /*
  2     功能: Eight queens
  3     时间: 2014-08-31 14:34:56
  4 */
  5 #include <stdio.h>
  6 
  7 int c = 1; //简单的分页
  8 
  9 void eightQueens(int *a, int i);    //递归求解
 10 int isDiagonal(int *a, int n);        //判断是否同对角线
 11 void printResult(int *a);            //输出结果
 12 
 13 int main(void)
 14 {
 15     int a[17];
 16     int i;
 17     
 18     //初始化棋盘
 19     for(i=0; i<17; i++)
 20     {
 21         a[i] = 0;
 22     }
 23 
 24     //求解方法
 25     eightQueens(a, 1);
 26     
 27     return 0;
 28 }
 29 
 30 void eightQueens(int *a, int i)
 31 {
 32     int j;
 33 
 34     if(a[0]==1)
 35     {
 36         //输出结果
 37         printResult(a);
 38     }
 39     else
 40     {
 41         for(j=1; j<9; j++)
 42         {
 43             if(a[j] != 1 && isDiagonal(a, i*10+j)) //非同行、非同列、不再对角线。
 44             {
 45                 a[j] = 1;
 46                 a[8+i] = i*10+j;
 47                 if(i == 8) a[0] = 1;
 48                 //递归
 49                 if(i<=8)
 50                 {
 51                     eightQueens(a, i+1);
 52                 }
 53                 a[j] = 0;
 54                 a[8+i] = 0;
 55                 a[0] = 0;
 56             }
 57         }
 58     }
 59     
 60 }
 61 
 62 //判断是否同对角线
 63 int isDiagonal(int *a, int n)
 64 {
 65     int aDcd, aBit;    //已标记的行列坐标
 66     int nDcd, nBit; //待判断的行列坐标
 67     int tDcd, tBit; //已标记与待判断行列差值
 68     int k;
 69 
 70     nDcd = n/10;
 71     nBit = n%10;
 72 
 73     for(k=9; k<17; k++)
 74     {
 75         if(a[k] != 0)
 76         {
 77             //分离已标记坐标的行与列
 78             aDcd = a[k]/10;
 79             aBit = a[k]%10;
 80             
 81             tDcd = nDcd - aDcd; //计算行差值
 82             tBit = nBit - aBit; //计算列差值
 83 
 84             if((tDcd-tBit) == 0 || (tDcd + tBit) == 0) //行列差值的绝对值相等则在同对角线
 85             {
 86                 return 0;
 87             }
 88         }
 89         else
 90         {
 91             return 1;
 92         }
 93     }
 94     return 1;
 95 }
 96 
 97 //输出结果
 98 void printResult(int *a)
 99 {
100     int m; 
101 
102     printf("Scheme %d :\n", c);
103     for(m=9; m<17; m++)
104     {
105         printf("a[%d]\t", a[m]);
106     }
107     printf("\n");
108     
109     c++;
110 
111     if(c%10 == 0){
112         getchar();
113     }
114 }
View Code

C语言学习才开始,许多还不太熟悉,还没看到算法,只是凭自己想的写的,比较粗糙,至于优化之类留与后期吧。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。