递归题目练习---N皇后问题

简介: 递归题目练习---N皇后问题

N皇后问题


参考链接:https://www.cnblogs.com/henuliulei/p/10117304.html(讲解得很详细)


题目描述

请设计一种算法,解决著名的n皇后问题。这里的n皇后问题指在一个nxn的棋盘上放置n个棋子,使得每行每列和每条对角线上都只有一个棋子,求其摆放的方法数。给定一个int n,请返回方法数,保证n小于等于15


基本思路

皇后问题一个重要的判断该点能否取的标准是不能在同一行列和对角。判断约束函数判断第k个后能不能放在x[k]处 两个皇后不能放在统一斜线上: 若2个皇后放置的位置分别是(i,j)和(k,l), 且 i-j = k -l 或 i+j = k+l,则说明这2个皇后处于同一斜线上。


  1. 使用回溯法的思路

对皇后每一行不断进行尝试x[k],判断在此之上的数据时候会发生冲突,如果没有,则k+1.判断下一行。如果发生了冲突,就x[k]++继续进行尝试。当x[k] = = N时,表示此行完全没解,需要回溯到上一行,也就是进行k-1操作,在之前的基础是哪个x[k]++继续进行尝试。

当k = = N时,表明已经实现了一个n皇后的解,将x[k]数据输出则为解。随后,再上一次解的基础上,x[k]再次加一操作,进行下一个解的操作。

当时由于此解的最后一行必然已经没有解,所以k必然会回溯到上一行,k-1,在此摸索x[k]+1的其他解法。如果没有解,则不断的回溯到上一行k,然后再x[k]的基础上再次进行尝试。

知道最后k = =0,返回到第0行,表示已经无解,全部解法已输出。


  1. 使用递归法的思路

使用递归的方法是,对没有一行的位置x[k] = i,依次进行尝试,如果没有冲突,则进行递归进行下一行k+1;,当k = n时说明已经完成一次放置。但是由于处于递归上的其他位置还没有完成,循环没有结束,所以会不断递归查看全部位置是否合适。(感觉有点像广度优先遍历)


代码如下

#include<bits/stdc++.h>
using namespace std;
int n;
int x[100];
int sum=0;
/*
判断第k个后能不能放在x[k]处
两个皇后不能放在统一斜线上:
若2个皇后放置的位置分别是(i,j)和(k,l),
且 i-j = k -l 或 i+j = k+l,则说明这2个皇后处于同一斜线上。
*/
void output(){
    cout << "第" <<sum << "种放置方法为:" << endl;
 for(int i=1;i<=n;i++){
    cout << "(" <<i << "," << x[i] << ")" << endl;
 }
}
int place(int k){
   for(int j=1;j<k;j++){
      if(x[j]==x[k] || abs(x[j]-x[k])== abs(j-k)) //对于此时的x[k],在此之上的同一列和对角线存在冲突
         return 0;  //表示不能放
   }
   return 1;  //表示可以放
}
void BackTrace(int t,int n){//递归
    if(t>n){如果t>n说明已经完成一次放置
        sum++;
        output();
    }
    else{
        for(int i=1;i<=n;i++){
           x[t]=i;
           if(place(t)){// //可以放在i位置处,则继续搜索
              BackTrace(t+1,n);
           }
        }
    }
}
void BackTrace1(int n){//非递归
   int k;
   x[1]=0;
   k=1;
   while(k>=1){
    x[k]+=1;先放在第一个位置
    while((x[k]<=n && !(place(k)))){//如果不能放
        x[k]++;//  //放在下一个位置
    }
    if(x[k]<=n){
        if(k==n){// //如果已经放完了n个皇后
            sum++;
            output();
        }
        else{//  //没有处理完,让k自加,处理下一个皇后
            k++;
            x[k]=0;
        }
    }else{// 当前无法完成放置,则进行剪枝,回溯回去,回到第k-1步
      k--;
    }
   }
}
int main()
{
    memset(x,0,sizeof(x));
    cin >> n;
    cout << n << "皇后的放置方法为" << endl;
    BackTrace(1,n);
    //BackTrace1(n);
    return 0;
}

image.png

目录
相关文章
|
6月前
函数递归详解----跳台阶、斐波那契数列、汉诺塔问题
递归的思想:把⼀个⼤型复杂问题层层转化为⼀个与原问题相似,但规模较⼩的⼦问题来求解;直到⼦问题不能再被拆分,递归就结束了。所以递归的思考⽅式就是把⼤事化⼩的过程。递归中的递就是递推的意思,归就是回归的意思。
|
移动开发 算法
DFS深度优先算法 —— AcWing 842. 排列数字AcWing 843. n-皇后问题
DFS深度优先算法 —— AcWing 842. 排列数字AcWing 843. n-皇后问题
102 0
剑指offer_递归与循环---跳台阶
剑指offer_递归与循环---跳台阶
59 0
剑指offer_递归与循环---矩形覆盖
剑指offer_递归与循环---矩形覆盖
76 0
剑指offer_递归与循环---斐波那契数列
剑指offer_递归与循环---斐波那契数列
62 0
|
机器学习/深度学习
剑指offer_递归与循环---变态跳台阶
剑指offer_递归与循环---变态跳台阶
61 0
剑指offer_递归与循环---扑克牌顺子
剑指offer_递归与循环---扑克牌顺子
48 0
初学算法之---递归汉诺塔
初学算法之---递归汉诺塔
初学算法之递归---爬楼梯
初学算法之递归---爬楼梯