八皇后C++完整程序

八皇后问题一直都给人感觉是非常神秘的东西,想当年学人工智能,由于编程技术不足所以一直没动手实现过这个程序。

最近研究算法,编程技术暴增,搞定八个皇后自然是小菜一碟了。O(∩_∩)O~

今天用了回溯法实现一下这个程序。

在棋盘上放八皇后规则:

1. 行和列都不能有两个以上皇后

2. 对角线不能有两个以上的皇后

然后根据这些规则在棋盘上摆放皇后,如果能把所有皇后都摆上,那么就是有解,否则,无解。

之所以叫8皇后,是因为以前人们一直都在研究8个皇后的级数,后来8皇后解决之后,到16皇后,32皇后了,还是沿用这个名字了。

数量大了之后,就不是回溯法能搞定的了,要用到模拟退火法等高级的人工智能算法了。以后抽时间一并搞定。

本算法16皇后还是很轻松的,但是到了20个皇后之后就开始很吃力了,运行时间过长,如果是32个皇后的话,直接算不出来,呵呵,大家认为自己电脑牛逼的话可以试一试,不过应该都不可以。能用回溯法算出64皇后的电脑也许要等到量子计算机出现才可以了。

解决问题的关键就是主函数的循环写法,难点如下:

1  用一维数组代表棋盘,列数代表放置皇后的棋盘行,其值代表填在该行第几列

2. 用k表示填写到第几行了,一行一行地填写

3. 每到达新的行,这一行的vi值肯定是QUEENFREE,如果过发生回溯,那么这一行的值也重置为QUEENFREE。回到上一行的时候,这一行的值已经是前面填写的值了,因为通过判断这一行的值是否是QUEENFREE,而判断是否发生了回溯。回溯到上一行时,那么这行就不能填写被之前更小的值了,否则会发生无限循环。

4. 利用判断当前行是否达到了最大列数,判断这一行时候有合适值,如果没有就需要回溯到上一行了,回溯上一行前,记得充值当前行值为QUEENFREE。

5. 最后一行填写完毕,代表解完成了。

下面是完整的C++程序。

 

  1. #include<iostream>  
  2. #include<vector>  
  3.   
  4. using namespace std;  
  5.   
  6. class Solution {  
  7. public:  
  8.     const static int QUEENFREE = INT_MAX;  
  9.     bool eightQueens(vector<int> &vi, int n = 8)  
  10.     {  
  11.         vi.clear();  
  12.         vi.resize(n, QUEENFREE);  
  13.         int k = 0;  
  14.         while (k>=0)  
  15.         {   //k代表即将需要填入皇后的行数  
  16.             int i = 0;  
  17.             for (; i < n; i++)   //i代表在这一行填入皇后的列数  
  18.             {  
  19.                 if(islegalMove(vi, k, i))  
  20.                 {  
  21.                     //如果vi[k]不等于QUEEFREE那么就是说明,这是从下一层返回来的k值。  
  22.                     //第一次进入该层就应该满足条件就填写了,但是如果是下一层返回来的话,  
  23.                     //就不能填写比前值更小的值了,这也是Backtracking算法的一个特征:  
  24.                     //是按一定循序的值循环探索适合的解。  
  25.                     //这里不用栈,只用k执行了差不都是栈的功能。  
  26.                     if(vi[k] == QUEENFREE || vi[k]<i)  
  27.                     {  
  28.                         vi[k] = i;  
  29.   
  30.                         //判断已经填到了最后一行了,那么就是成功了。  
  31.                         if (k == n-1) return true;  
  32.                         k++;  
  33.                         break;  
  34.                     }  
  35.                 }  
  36.             }  
  37.             if (i == n)   
  38.             {  
  39.                 //k行填写了所有可能的值都不符合要求,那么就返回上一层,  
  40.                 //这时候需要把k行还原为原始状态,代表返回了上一行,这样方便上面判断  
  41.                 vi[k] = QUEENFREE;  
  42.                 k--;  
  43.             }  
  44.         }  
  45.         //最后Backtracking到了根,那么就是没有解了。  
  46.         return false;  
  47.     }  
  48.       
  49.     bool islegalMove(vector<int> &vi, int row, int col)     
  50.     {  
  51.         //判断列是否符合规定  
  52.         for (int i = 0; i < vi.size(); i++)  
  53.         {  
  54.             if(i != row && vi[i] == col)  
  55.                 return false;  
  56.         }  
  57.         //判断对角线是否符合规定,后面的判定公式费点神。  
  58.         for(int i = 0; i < vi.size(); i++)  
  59.         {  
  60.             if(i != row && (vi[i]-i == col-row || vi[i]+i == col+row))  
  61.             {  
  62.                 return false;  
  63.             }  
  64.         }  
  65.         //不用判断行了,因为默认是一行只填一个queen的。  
  66.         return true;  
  67.     }  
  68. };  
  69.   
  70. int main()  
  71. {  
  72.     vector<int> queen;  
  73.     Solution solu;  
  74.     if(solu.eightQueens(queen,8))  
  75.         for(auto x: queen)  
  76.         {  
  77.             for (int i = 0; i < queen.size(); i++)  
  78.             {  
  79.                 if (i == x)  
  80.                 {  
  81.                     cout<<x<<"QUEEN"<<"\t";  
  82.                 }  
  83.                 else  
  84.                 {  
  85.                     cout<<"#"<<"\t";  
  86.                 }  
  87.             }  
  88.             cout<<endl;  
  89.         }  
  90.     else cout<<"No solution!";  
  91.     cout<<endl;  
  92.     return 0;  
  93. }  


结果:

4皇后:

8皇后:

16皇后:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值