八皇后问题

 八皇后是一道很具典型性的题目。它的基本要求是这样的:在一个8*8的矩阵上面放置8个物体,一个矩阵点只允许放置一个物体,任意两个点不能在一行上,也不能在一列上,不能在一条左斜线上,当然也不能在一条右斜线上。

    初看到这道题目,大家的第一印象是遍历,但是经过实践之后发现遍历其实不好写,而且复杂度很低。不仅需要遍历8*8*8*8*8*8*8*8*8 = 2^24次数据,还要判断各种条件,实际的计算复杂度还要比较这个高。其实我们仔细看一看,这中间很多的计算其实很多是不需要的,因为如果我们在某一行没有可以插入的数据的话,那么这后面的行其实就不用考虑了。也就是说,我们只有在保证前面 插入的物体都合法有效的情况下,才能进行下一次的物体插入。无谓的遍历只会是无用功。

   那么,我们应该怎么做呢?其实步骤不太难:

    (1)在第n行寻找可以插入的位置,中间涉及到位置合法性的判断

    (2)如果没有可以插入的位置,返回

    (3)如果有可以插入的位置, 插入数据。此时再判断是否已经是最后一行,如果是,打印输出返回;反之继续对下一行数据进行试探处理。

    有了上面的步骤,我们就可以书写代码了。老规矩,朋友们可以自己先尝试一下。

    a)定义全局堆栈和打印函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int gEightQueen[8] = {0};  
  2. static int gCount = 0;  
  3.   
  4. void print()  
  5. {  
  6.     int outer;  
  7.     int inner;  
  8.   
  9.     for(outer = 0; outer <8; outer ++){  
  10.         for(inner = 0; inner < gEightQueen[outer]; inner ++)  
  11.             printf("* ");  
  12.   
  13.         printf("# ");  
  14.   
  15.         for(inner = gEightQueen[outer] + 1; inner < 8; inner ++)  
  16.             printf("* ");  
  17.   
  18.         printf("\n");  
  19.     }  
  20.   
  21.     printf("=====================================\n");  
  22. }  
     b)添加位置合法性的函数判断

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int check_pos_valid(int loop, int value)  
  2. {  
  3.     int index;  
  4.     int data;  
  5.   
  6.     for(index = 0; index < loop; index ++){  
  7.         data = gEightQueen[index];  
  8.   
  9.         if(value == data)  
  10.             return 0;  
  11.   
  12.         if((index + data) == (loop + value))  
  13.             return 0;  
  14.   
  15.         if((index - data) == (loop - value))  
  16.             return 0;  
  17.     }  
  18.   
  19.     return 1;  
  20. }  
     c) 八皇后遍历

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void eight_queen(int index)  
  2. {  
  3.     int loop;  
  4.   
  5.     for(loop = 0; loop < 8; loop++){  
  6.         if(check_pos_valid(index, loop)){  
  7.             gEightQueen[index] = loop;  
  8.   
  9.             if(7 == index){  
  10.                 gCount ++, print();  
  11.                 gEightQueen[index] = 0;  
  12.                 return;  
  13.             }  
  14.               
  15.             eight_queen(index + 1);  
  16.             gEightQueen[index] = 0;  
  17.         }  
  18.     }  
  19. }  

总结:

    (1)迭代递归是编程的难点,需要自己好好实践,看别人写一百遍,不如自己写一遍

    (2)递归的时候务必注意函数return的出口

    (3)递归函数中语句的顺序不要随意更换

    (4)递归函数中注意数据的保存和恢复

    (5)递归函数也要验证,可以用程序验证法,也可以用其他函数的结果来验证


ps:

    下面是完整的代码,大家可以直接保存成queue.cpp,直接编译运行即可。可以打印出所有92种情况,

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. static int gEightQueen[8] = {0};  
  5. static int gCount = 0;  
  6.   
  7.   
  8. void print()  
  9. {  
  10.     int outer;  
  11.     int inner;  
  12.   
  13.     for(outer = 0; outer <8; outer ++){  
  14.         for(inner = 0; inner < gEightQueen[outer]; inner ++)  
  15.             printf("* ");  
  16.   
  17.         printf("# ");  
  18.   
  19.         for(inner = gEightQueen[outer] + 1; inner < 8; inner ++)  
  20.             printf("* ");  
  21.   
  22.         printf("\n");  
  23.     }  
  24.   
  25.     printf("=====================================\n");  
  26. }  
  27.   
  28. int check_pos_valid(int loop, int value)  
  29. {  
  30.     int index;  
  31.     int data;  
  32.   
  33.     for(index = 0; index < loop; index ++){  
  34.         data = gEightQueen[index];  
  35.   
  36.         if(value == data)  
  37.             return 0;  
  38.   
  39.         if((index + data) == (loop + value))  
  40.             return 0;  
  41.   
  42.         if((index - data) == (loop - value))  
  43.             return 0;  
  44.     }  
  45.   
  46.     return 1;  
  47. }  
  48.   
  49.   
  50.   
  51. void eight_queen(int index)  
  52. {  
  53.     int loop;  
  54.   
  55.     for(loop = 0; loop < 8; loop++){  
  56.         if(check_pos_valid(index, loop)){  
  57.             gEightQueen[index] = loop;  
  58.   
  59.             if(7 == index){  
  60.                 gCount ++, print();  
  61.                 gEightQueen[index] = 0;  
  62.                 return;  
  63.             }  
  64.               
  65.             eight_queen(index + 1);  
  66.             gEightQueen[index] = 0;  
  67.         }  
  68.     }  
  69. }  
  70.   
  71.   
  72.   
  73. int main(int argc, char* argv[])  
  74. {  
  75.     eight_queen(0);  
  76.     printf("total = %d\n", gCount);  
  77.     return 1;  
  78. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值