算法系列——八皇后问题

public class Queen {
    private final int size;
    private int[] location;
    private int[] columnOccupied;
    private int[] lineOccupied;            //对角线
    private int[] reverseLineOccupied;     //反对角线
    private static int solveCount;
    private static final int locationOccupied = 1;
    private static final int unLocationOccupied = 0;

    public Queen(int size){
        this.size = size;
        location = new int[size];
        columnOccupied = new int[size];
        lineOccupied= new int[2*size];
        reverseLineOccupied = new int[2*size];
    }

    public void printLocation(){
        System.out.println("第"+solveCount+"方法");
        for(int i=0;i<size;i++){
            System.out.println("行"+i+"列"+location[i]);
        }
    }

    private boolean isOccupied(int i,int j){
        return(columnOccupied[j]==locationOccupied)||                   //列被占据
            (lineOccupied[i-j-1+size]==locationOccupied)||              //斜线被占据
                (reverseLineOccupied[i+j]==locationOccupied);          //反斜线被占
    }

    public void setLocation(int i,int j,int flag){
        columnOccupied[j] = flag;
        lineOccupied[i-j-1+size] = flag;
        reverseLineOccupied[i+j] = flag;
    }
    public void place(int i){
        for(int j=0;j<size;j++){
            if(!isOccupied(i,j)){
                location[i] = j;
                setLocation(i,j,locationOccupied);

                if(i<size-1){
                    place(i+1);

                }else{
                    solveCount++;
                    printLocation();

                }
                setLocation(i,j,unLocationOccupied);
            }
        }
    }
    public  void start(int i){
        place(i);
    }

    public static void main(String[] args){
          new Queen(8).start(0);

    }

}

代码来自   http://blog.163.com/[email protected]/blog/static/250344322011273515769/  ,作者写的真漂亮。

八皇后问题在放置每个皇后时要满足没有别的皇后在同一条线上,包括同一列(j),同一行(i),同一斜线(i-j-1+size),同一反斜线(i+j)。满足这四个条件就可以放置。

第一步:从第0行开始,place(0),查看第0行可以放置的列,方法是将所有的列遍历一遍,碰见第一个位置满足上述条件的就放进去,然后改变此位置的状态。

第二步:在place(0)中,递归调用place(1),在place(1)中,调用place(2)。。。这样,当所有位置放置完成,输出一种放置方法;另一种情况是到了后期无法放置;这两种情况发生后,程序都会取消这一步的操作,返回上一步,继续把没遍历完的j遍历完成,搜索所有可能情况。

比如当i=7时,如果j=2满足条件,由于i已达最大,所以可以将所有位置信息输出,输出之后,将i=7,j=2取消,从j=3开始,再次寻找合适情况。这样,就可以把i=7的所有可能j的情况都遍历到。完成后,退回上一步。

此时i=6,假设是以i=6,j=1的情况进入的i=7,那么就从i=6,j=2开始遍历j,满足时,再次进入i=7,j再从1开始。这样,把i=6的所有情况考虑完之后,退回i=5.这种方法称为回溯法。

回溯法(英语:backtracking)是穷尽搜索算法(英语:Brute-force search)中的一种。

回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两
种情况:

* 找到一个可能存在的正确的答案
    * 在尝试了所有可能的分步方法后宣告该问题没有答案

在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。

时间: 2024-11-10 14:10:14

算法系列——八皇后问题的相关文章

递归之回朔算法应用----八皇后问题

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

回溯算法解八皇后问题(java版)

八皇后问题是学习回溯算法时不得不提的一个问题,用回溯算法解决该问题逻辑比较简单. 下面用java版的回溯算法来解决八皇后问题. 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 思路是按行来规定皇后,第一行放第一个皇后,第二行放第二个,然后通过遍历所有列,来判断下一个皇后能否放在该列.直到所有皇后都放完,或者放哪

经典回溯算法(八皇后问题)详解

八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题.该问题是十九世纪著名的数学家高斯1850年提出: 在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上 (斜率为1),问有多少种摆法.高斯认为有76种方案. 1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果. 计算机发明后,有多种方法可以解决此问题. 算法思路:    首先我们分析一下问题的解,我们每取出一个皇后,放入一行,共有八种不同的放法

回溯算法(八皇后问题)

八皇后问题 在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行.列和斜线的敌方棋子. 将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法? 程序实现 程序摘自回溯法与八皇后问题 #include<iostream> #include<math.h> using namespace std; int n=8; int total=0; int *c=new int(n); //下标为行数,存的数为列数 bool is_ok(int row

八皇后(JAVA算法实现)

在学习现代软件工程构建之法这门课时,老师要求发表一篇博客,使用JAVA算法实现八皇后问题的求解.写这篇博客时,我学习了一些其他的博客,因为我常常遇到问题,自己无法解决时,向他人学习也是一种方法. 国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 我们可以逐行或者逐列来进行可行摆放方案的遍历,每一行(或列)遍历出一个符合条件的 位置,接着就到下一行或列遍历下一个棋子的合适位置,这

python解决八皇后问题

经典回溯算法:八皇后问题 算法要求: 在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上. 国际象棋的棋盘如下图所示: 问共有多少种不同的方法,并且指出各种不同的放法. # -*- coding:utf-8 -*- __author__ = "tyomcat" print("******八皇后问题的解决方法******") def next_col(current, n=8): length = len(curr

递归的应用——八皇后问题

回朔算法的基本思想 ·从问题的某一种状态出发,搜索可以到达的状态 ·当某个状态到达后,可向前回退,并继续搜索其他可达状态 ·当所有状态都到达后,回朔算法结束 程序设计中可以利用函数的活动对象保存回朔算法的状态数据,因此可以利用递归完成回朔算法. 八皇后算法 1 初始化 I = 1 2 初始化 J = 1 3 从第i行开始,恢复j的当前值,判断第j个位置 A`位置j可放入皇后:标记位置(i,j),i++,转步骤2 B`位置j不可以放入皇后:j++,转至步骤A C`当j>8时,i--,转至步骤3 4

c++ 八皇后问题(转载)

转自 雪狼的程序故事 http://www.cnblogs.com/gaoteng/archive/2012/04/11/2442692.html 经典回溯算法(八皇后问题) 今天偶尔看到了一个算法问题(八皇后问题),回想一下还是在算法课上学习过的,于是,自己总结了一下,写了这篇日志 算法提出: 在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上.问共有多少种不同的方法,并且指出各种不同的放法. 算法思路: 首先我们分析一下问题的解,我们每取

【八皇后问题】 回溯算法

回溯算法:回溯算法实际上是一个类似枚举的搜索尝试方法,它的思想是在搜索尝试中寻找问题的解,当发现不满足求解条件时,就“回溯”返回,尝试别的路径.之前介绍的基础算法中的贪婪算法,动态规划等都具有“无后效性”,也就是在分段处理问题时,某状态一旦确定,将不再改变.而多数问题很难找到"无后效性”的阶段划分和相应决策,而是通过深入搜索尝试和回溯操作完成的. 八皇后问题:8*8的国际象棋棋盘中放八个皇后,是任意两个皇后不能互相吃掉.规则:皇后能吃掉同一行,同一列,同一对角线的任意棋子. 模型建立:不妨设八个