回溯法(一)——n皇后问题

《回溯法(一)——n皇后问题》

问题描述

在一个n*n的棋盘上放置皇后,要求:一个皇后的同一行、同一列、同一条对角线上不允许出现其他皇后。请给出所有的放置方案。

《回溯法(一)——n皇后问题》

算法思路

思路很简单,由于每行每列不能出现两个皇后,因此每行只能放一个皇后,那么第i行中皇后究竟应该放哪儿呢?我们可以从第i行第一列开始依次向后逐格判断,看看若放在当前位置是否会冲突,若不冲突,则继续考虑下一行,若冲突,则继续向后移动一格,再判断。
若i行所有的位置都不满足,则回溯,将i-1行皇后的位置往后移动,直到找到一个合理的位置,再继续从前往后寻找i行的位置。

示例

求解4皇后问题。

  1. 寻找第一行插入点:首先将Q放置a[0][0],无冲突;
  2. 寻找第二行插入点:a[1][0]、a[1][1]均冲突,a[1][2]可行;
  3. 寻找第三行插入点:发现所有格子都冲突,此时要发生回溯!
    《回溯法(一)——n皇后问题》

  4. 回到第二行,继续向后寻找插入点,找到a[1][3];

  5. 寻找第三行插入点:a[2][1]
  6. 寻找第四行插入点:发现所有位置都冲突,则回溯!
    《回溯法(一)——n皇后问题》

  7. 寻找第三行插入点:发现全都冲突,则继续回溯;

  8. 寻找第二行插入点:发现全都冲突,则继续回溯;
  9. 寻找第一行插入点:a[0][1];
  10. 寻找第二行插入点:a[1][3];
  11. 寻找第三行插入点:a[2][0];
  12. 寻找第四行插入点:a[3][2],此时找到一种方案。
    《回溯法(一)——n皇后问题》

数据结构

result数组:存储结果集。

  • 下标表示行号;
  • result[i]表示第i行皇后的列号。

代码实现

/** * N皇后问题 * @param n 矩阵规模 * @param i 行号 * @param result 皇后的结果集(下标表示行号,值表示列号) */
void NQueen( int n, int i, int[] result ){
   for( int j=0; j<n; j++ ){
        if ( canPlace(n,i,j,result) ){
            result[i] = j;
            if ( i==n-1 ) {
                printResult(result);
            }
            else {
                NQueen(n,i+1,result);
            }
        }
   } 
}

/** * 判断第i行第j列能不能放 * @param n 矩阵规模 * @param i 行号 * @param j 列号 * @param result 皇后的结果集(下标表示行号,值表示列号) */
private boolean canPlace(int n, int i, int j, int[] result){
    for( int z=0; z<i; z++ ){
        // 判断列号是否相同、是否在对角线上(长、宽是否相等)
        if ( j==result[z] || (i-z)==Math.abs(j-result[z]) )
            return false;
    }
    return true;
}

/** * 打印结果集 * @param result 结果集 */
private void printResult(int[] result){
    for( int i=0; i<result.length; i++ ){
        System.out.println("第"+i+"行,第"+result[i]+"列"); 
    }
}

《回溯法(一)——n皇后问题》

    原文作者:回溯法
    原文地址: https://blog.csdn.net/u010425776/article/details/70142539
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞