八皇后问题回溯法和迭代法

作者: _兜兜转转_ | 来源:发表于2019-03-23 22:13 被阅读14次

数据结构系列文章:

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。

回溯法[试探法,递归]和迭代法

基本思路是:
1.第一行先占一个皇后
2.第二行再占一个且不能与第一个皇后攻击
3.第三行再占一个
。。。。。
n.第n行占一个,当第n行站不下的时候,取消n-1行的皇后,在第n-1皇后的下一个位置重新占一个皇后位置,知道占到最n-1行的最后一个位置,当还不行的时候,就取消第n-2行,当n-2行的皇后在n-2行的最后一个位置的时候,就取消n-3,n-2在最后一个位置,那么n-3行的一定不再最后一个位置。
再重新寻找n-2行的皇后的位置。

。。。。
。。。。
直到找到最后一个皇后。

找完第一种解法,重新开始寻找第二种解法,直接第一个皇后占第一行的第2个位置,寻找第三种解法占第一行的第3个位置。。。。直到寻找第n个解法。code 在下边。代码是Swift,正好可以练习练习语法。


struct QueenHandle {
//一次的解法皇后
   var queensArray:[Queen] = [Queen]();
//所有解法
   var queensWay:[[Queen]] = [[Queen]]();
   
   init() {
   }
   func canStandWithOthers(queens:[Queen],queen:Queen) -> Bool {
       var pass = true;
       let count = queens.count;
       if count == 0 {
           return true;
       }
       for k in 0..<count{
           let qSub = queens[k];
//是否存在打架行为
           if qSub.unrejectWith(queen: queen) == false{
               //有能打架的皇后
               pass = false;
               break;
           }
       }
       return pass;
   }
//回溯法
   mutating func callback(x:inout Int,y:inout Int , n:inout
       Int,xMax:Int,yMax:Int) -> Void {
       let q = Queen(locations: Point(x: x, y: y));
//位置是否可用
       let can = self.canStandWithOthers(queens: self.queensArray, queen: q);
       if can {
//添加皇后
           self.queensArray.append(q);
           y += 1;
           x = 0;
           if y > yMax
           {
               if (self.queensArray.count == n){
//解法完毕 继续下一个解法
               self.queensWay.append(self.queensArray);
                   self.queensArray.removeAll();
                   x = self.queensWay.count;
                   y = 0;
                   if (x == n){return}else{
                       callback(x: &x, y: &y, n: &n, xMax: xMax, yMax: yMax);
                   }
               }else{
//回溯法核心思路 当n行没有合适位子,删除上一行的皇后,重新寻找上一行的新皇后位子
                   if self.queensArray.count > 0{
                       let lastQ = self.queensArray.removeLast();
                       x = lastQ.locations.x + 1;
                       y -= 1;
                   }
               }
           }else if(y <= yMax){
               callback(x: &x, y: &y, n: &n, xMax: xMax, yMax: yMax);
           }
       }else if(x < xMax){
           x += 1;
           callback(x: &x, y: &y, n: &n, xMax: xMax, yMax: yMax);
       }else if(x >= xMax){
           if self.queensArray.count > 0{
               let lastQ = self.queensArray.removeLast();
               x = lastQ.locations.x + 1;
               y -= 1;
               if x > xMax{
                   let lastQ = self.queensArray.removeLast();
                   x = lastQ.locations.x + 1;
                   y -= 1;
               }
               callback(x: &x, y: &y, n: &n, xMax: xMax, yMax: yMax);
           }
       }
   }
   public mutating func handle() -> Void {
       var number = 0
       while number<8 {
           self.find(index: number);
           //首行的8种可能
           if self.queensArray.count == 8 {
               self.queensWay.append(self.queensArray);
           }
           self.queensArray.removeAll();
           number += 1;
       }
   
   }
   public mutating func find(index:Int) -> Void
{
   var y = 0;
   var x = index;
   while y<8 {
       while x<8{
           let queen = Queen(locations: Point(x: x, y: y));
           let count = self.queensArray.count;
           
           if count>0 {
               var pass = true;
               for k in 0..<count{
                   let qSub = self.queensArray[k];
                   if qSub.unrejectWith(queen: queen) == false{
                       //有能打架的皇后
                       pass = false;
                       break;
                   }
               }
               if pass{//添加成功
                   self.queensArray.append(queen);
                   break;
               }else{
                   x += 1;
               }
           }else{//添加成功跳出循环
               self.queensArray.append(queen);
               break;
           }
       }
       //每一行找出一个 跳下一行
       if(self.queensArray.count == y+1){
           y += 1;
           x = 0;
       }else{
           if self.queensArray.count > 0{
               while x > 7{
                   //回溯法 寻找上一个可能的皇后 当x==8,继续找上一行的皇后
                   x = self.queensArray.removeLast().locations.x + 1;
                   y -= 1;
               }
           }else{
               y += 1;
           }
       }
   }
}
   public func printWays() -> Void{
       let count = self.queensWay.count;
       for i in 0..<count {
           let queens = self.queensWay[i];
           let countSub = queens.count;
           for j in 0..<countSub{
               let q = queens[j];
               q.printQueen();
           }
           print("--------------------");
       }
   }
}

点我下载代码

相关文章

  • 八皇后问题回溯法和迭代法

    数据结构系列文章: 常用的排序 二叉树的4种遍历 八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型...

  • N皇后

    回溯法核心代码: n皇后问题回溯法

  • LeetCode 51. N-Queens

    Leetcode : N-QueensDiffculty:Hard N皇后问题,对八皇后问题的扩展,典型的回溯法算...

  • 回溯法 八皇后问题

    问题描述 要在8*8的国际象棋中放八个皇后,使任意两个皇后不能相互吃掉,在同一行,同一列,同一对角线会相互吃掉,求...

  • 八皇后问题c语言算法

    目录[TOC] 问题分析: 相信八皇后规则的问题,大家都很熟悉,接下来是如何分析回溯法的应用。回溯法与图里面的深度...

  • 51. N-Queens

    题目分析 N 皇后问题 + 回溯法 代码

  • 回溯法解八皇后问题

    问题介绍 摘自百度百科八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟...

  • 暴力穷举和回溯法(八皇后问题)

    以前每次遇到算法问题都是直接暴力求解,一直以为自己用的是暴力穷举法,现在学了回溯法,发现部分问题其实使用的是回溯法...

  • 回溯法初探(一)

    回溯法是的应用范围很广,主要用于数据量不是很大的暴力求解问题,比如"图的m着色问题","八皇后问题"。 ...

  • 【洛谷 P1219】八皇后

    八皇后(题目链接) 思路 典型的深搜回溯问题 代码

网友评论

    本文标题:八皇后问题回溯法和迭代法

    本文链接:https://www.haomeiwen.com/subject/ovuevqtx.html