N皇后问题
- 描述:
N*N网格中放N个皇后,要求每二个皇后不在同一行同一列同一斜线。返回摆法的数量。
- 解法:
暴力递归,深度优先,递归探讨每一行,探讨(for)该行的所有valid列,放过皇后的列记录下来,继续往下一行递归,所要种类数,记录所有该行该列的种类数,累加返回就是该行的种类总数。边界条件,就是顺利完n行的返回1(一种摆法)。
/**
* @file queen.cpp
* @author Stephen Ding (1103037805@qq.com)
* @brief
* @version 0.1
* @date 2022-04-17
*
* @copyright Copyright (c) 2022
*
*/
#include <iostream>
#include <math.h>
using namespace std;
class NQueen{
public:
int NQueenMethod(int n = 0){
// n 表示 N个皇后,N*N网格
if(n < 1) return 0;
int record[n]; // i : 0 ~ n-1 表示第i行,存储的数值j表示在该行的第j列放一个皇后
return Process(0, record, n); // 从第0行开始,逐行处理
}
/**
* @brief
*
* @param i 来到第i行
* @param record 从上一行正确摆完后传过来的记录,即 0 ~ i-1 已经摆好了,剩下 i ~ n - 1 没有摆
* @param n 定值
* @return int 告诉上一行 你这种摆法,从我这一行(i)到下面 i ~ n - 1 能正确摆多少种方法
*/
int Process(int i, int record[], int n){
if(i == n) return 1; // 边界条件,能够走通所有的行,即到达终止行,即是一种摆法
int res = 0;
// 遍历我这一行的所有的列,可以放一个皇后的列都进去,往下面去寻找多少种摆法,总和就是返回值
for(int j = 0; j < n; ++j){
if(isValid(record, i, j)){
// 第j列可以放
// 尝试在该列放,那么能有多少种摆法呢
record[i] = j;
int temp = Process(i+1, record, n);
// 累加
res = res + temp;
}
}
return res;
}
bool isValid(int record[], int i, int j){
// 只要确定 当前行i,在第j列摆放一个皇后,会不会和其他行的数值比较是否 同列 或者 同斜线
for(int k = 0; k < i; ++k){
if(record[k] == j || abs(i - k) == abs(j - record[k])){
return false;
}
}
return true;
}
};
int main (int argc, char** argv){
NQueen test;
int res = test.NQueenMethod(8);// res == 92;
cout << res << endl;
}