八皇后问题的回溯和递归方法

1、回溯法

用一维数组记录皇后的位置。数组的下标代表皇后所处的行,下标对应的值代表皇后所处的列。用count记录皇后的个数,当count小于queen数时,在循环体中寻找合适位置的queen。寻找queen:从列1依次寻找,满足条件则count+1,继续从列1处寻找下一个queen。如全部找完没找到合适的位置,则count-1,从第count个皇后所在列的下一位置开始继续循环。

public class Queen {

       public void queenInstance(int num ) {
             if (num < 1 )
                   throw new IllegalArgumentException();
             // store the position of the queen
             int[] queen = new int[num + 1];
             // store the queen count
             int count = 1;
             queen[ count] = 1 ;

             while (count > 0 ) {
                   while ((count <= num ) && (queen [count ] <= num)) {
                         if (! isValid( queen, count ))
                               queen[ count] ++;
                         else {
                               count++;
                               if( count <= num)
                                     queen[ count] = 1 ;
                         }
                   }
                   if (count > num ) {
                         for (int i = 1; i <= num ; i++ )
                               System. out.println ("(" + i + ", " + queen[i] + ")") ;
                         break;
                   }
                   count--;
                   queen[ count] ++;
             }
       }

       private boolean isValid(int a [], int count) {
             for (int i = 1; i < count ; i++ )
                   if (a [i ] == a[ count] || ( i - count == a[ i] - a [count ])
                               || (i - count == a [count ] - a[ i]))
                         return false;
             return true;
       }

       public static void main(String ... args) {
             Queen queen = new Queen ();
             queen. queenInstance(8);
       }

2、位运算法

考虑到我们寻找皇后是按照行的顺序依次寻找,因此在程序中,行的信息可以省略,每次的寻找实际上是为了在列中找到一个合适的位置。因此我们用一个int值(当然long也可以),将其第1到列总数的位置为1。这里我们通过将1左移num位减去1得到。函数test方法的三个参数分别是:皇后占用的位、左对角线皇后占用的位、右对角线皇后占用的位置。每次递归中,首先判断row是否等于upplim,等于则说明所有位被皇后占用,递归结束,得到一个解。若不相等,寻找可用的位(upplim & ~(row | ld | rd)),然后判断是否为0,为0说明全被占用,递归结束,未寻找到可行解。若不为0,则依次把所有可以放置皇后的位放置皇后,然后调用递归方法。

public class Queen {

       private int upplim;
       private int sum;

       public void queenCalculate(int num ) {
             if (num < 1 || num >= 31 )
                   throw new IllegalArgumentException();
             upplim = (1 << num ) - 1;
             sum = 0;
             test( 0, 0 , 0) ;
       }

       private void test(int row , int ld, int rd) {
             if (row != upplim ) { // row不满,即皇后未放置完全
                   int pos = upplim & ~( row | ld | rd) ; // 寻找空闲位置
                   while (pos != 0 ) { // 仍有可以放置皇后的位置
                         int p = pos & -pos ; // 取出最右边的1
                         pos -= p; // 把皇后放在最右边的1的位置
                         test( row + p, ( ld + p) << 1 , (rd + p ) >> 1) ; // 对下一行调用递归方法
                   }
             } else
                   sum++;
       }

       public static void main(String ... args) {
             Queen queen = new Queen ();
             queen. queenCalculate(12);
             System. out.println (queen .sum + " " );
       }
}

八皇后问题的回溯和递归方法,布布扣,bubuko.com

时间: 2024-10-07 21:15:28

八皇后问题的回溯和递归方法的相关文章

八皇后问题(回溯法&amp;枚举法)

作者 : 卿笃军 本文讨论了八皇后问题的三种解决方案: 一.枚举法 二.回溯法(递归版) 三.回溯法(非递归版) 本来这些代码是以前编写好的,没有发表,由于最近又学习到了八皇后问题,自己整理了一下发表了出来! 首先.说明一下何为八皇后问题,我也不去谷歌了,直接简单的说明一下: 八皇后问题,就是在一个8*8的平面棋盘上,要求你摆放8个棋子,要求:这8个棋子不能有2个在同一行,也不能有2个在同一列,同时一条斜线上面也不能有2个~~~~ 比如:4*4的棋盘,你可以这样摆放(4皇后问题): 以上图为参照

八皇后问题——递归+回溯法

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果. 求解过程: 采用遍历的办法,就是采用将每种情况都验证的办法最终找出问题的解,但是蛮力遍历的话,需要遍历的数据量太大,计算时间花费太大,所以在遍历

【八皇后问题】 回溯算法

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

八皇后解法(回溯法)

package com.company; /** * Created by Administrator on 2016/9/15. */public class EigthQueue { private static int N = 8; private int count = 0; // 总方案数 private int[] flag = {-1, -1, -1, -1, -1, -1, -1, -1}; //回溯法递归实现八皇后问题 //输出棋盘 private void printChes

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

八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 代码实现 static int count = 0;//记录有几种方法 int max = 8;//max表示几个皇后 int[] arr = new int[max];//用一个数组表示,其中arr[n]表示放在第arr[n]+1列,n表示第n+1个

八皇后(dfs+回溯)

重看了一下刘汝佳的白板书,上次写八皇后时并不是很懂,再写一次: 方法1:逐行放置皇后,然后递归: 代码: #include <bits/stdc++.h>#define MAXN 8#define ll long longusing namespace std; ll ans=0;int c[MAXN]; void dfs(int cur){    if(cur==MAXN) ans++;   //***因为是逐行放置的,所以只要走到最后一行则肯定可行    else    {       

八皇后问题(回溯)

public class Queen {          int QUEEN_COUNT = 8;    //随便你定义几个皇后了,你可以循环产生a个到b个皇后的解     static final int EMPTY = 0;  //如果count[x][y] == EMPTY ,则可以放置皇后:反之,其正上方或斜上方必己放置皇后     int[][] count = new int[QUEEN_COUNT][QUEEN_COUNT]; //     int[] QueenIndex = 

八皇后问题之回溯法

#include <math.h> #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define N 20 int n, sum, x[N+1]; // n:问题规模 sum:方案数目 x[]方案存储 void Init() { cout << "输入皇后问题规模:&qu

八皇后以及N皇后问题分析

八皇后是一个经典问题,在8*8的棋盘上放置8个皇后,每一行不能互相攻击. 因此 拓展出 N皇后问题. 下面慢慢了解解决这些问题的方法: 回溯法: 回溯算法也叫试探法,它是一种系统地搜索问题的解的方法. 回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试. 在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满足某种要求的可能或最优的情况,从而得到整个问题的解. 回溯算法就是解决这种问题的“通用算法”,有“万能算法”之称. N皇后问题在N增大时就是这样一个解