已知正整数n,即在一个nxn的棋盘上放置n个棋子,使每行每列和每条对角线上都只有一个棋子,返回有多少种摆法方法。保证n小于等于15。
例如当输入4时,对应的返回值为2,
对应的两种四皇后摆位如下图所示:
class Queens {
public:
int nQueens(int n) {
// write code here
int count=0;
int *a=new int[n+1];
Queens1(a,1,n,count);
return count;
}
void Queens1(int a[],int i,int n,int &count){
if(i>n){
count++;
return ;
}
for(int j=1;j<=n;j++){
a[i]=j;
if(Place(a,i))
Queens1(a,i+1,n,count);
}
}
bool Place(int *a,int i){
for(int j=1;j<i;j++)
if((a[j]==a[i])||(a[j]-a[i]==(j-i))||(a[j]-a[i]==i-j))
return 0;
return 1;
}
};
public class Queens {
public static int nQueens(int n) {
int[] cols = new int[n];
int[] num = { 0 };
for (int i = 0; i < n; i++) {
cols[0] = i;//第一行皇后的位置
getCount(cols, 1, num);
}
return num[0];
}
//除了第一行外,每行赋值皇后的位置,并判断位置是否合理,若能成功赋值最后一行
//位置,方法数+1;
public static void getCount(int[] cols, int row, int[] num) {
if (row == (cols.length)) {
num[0]++;
return;
}
for (int i = 0; i < cols.length; i++) {
if (checkValid(cols, row, i)) {
cols[row] = i;
getCount(cols, row + 1, num);
}
}
}
// 判断插入的皇后位置是否合理
private static boolean checkValid(int[] cols, int row, int col) {
for (int i = 0; i < row; i++) {
int temp = cols[i];
if (temp == col)
return false;
if (Math.abs(row - i) == Math.abs(temp - col))
return false;
}
return true;
}
}
import java.util.*;
public class Queens {
public int nQueens(int n) {
// write code here
if(n<=0)
return 0;
int[] pos = new int[n];
for (int i=0;i<n;i++)
pos[i] = Integer.MIN_VALUE;
int res = 0;
int i=0,j=0; //i进行行扫描,j进行列扫描
while (i<n){ //对每行进行扫描
while(j<n){ //对每列进行扫描
if (NoClash(i, j, pos)){//如果此位置可以放置一个皇后
pos[i] = j;
j=0; //下一行从第一列开始探索
break;
}
else { //如果此列不能够放置一个皇后
j++;
}
}
if (pos[i] == Integer.MIN_VALUE){ //如果此行没有解,进行回溯
if(i == 0) //i是第一行了,说明没有解了
break;
i--; //回到上一行
j = pos[i]+1; //j从上一行的原位置+1开始搜索
pos[i] = Integer.MIN_VALUE; //清除第i行的皇后
continue;
}//if
else{ //此行有解
if(i==n-1){ //在最后的一行找到了位置,即找到了解
res++;
j = pos[i] + 1;
pos[i] = Integer.MIN_VALUE;
continue;
}//if
}
i++; //进行下一行探索
}//while
return res;
}
boolean NoClash (int row, int col,int[] chessboard){ //判断皇后是否产生冲突,没有冲突返回true
for(int i=0;i<chessboard.length;i++){
if(chessboard[i] == col|| Math.abs(i-row)==Math.abs(chessboard[i]-col)){
return false;
}
}
return true;
}//Clash
}
class Queens {
public:
int cnt=0,N;
bool col[15],dpos[30],dneg[30];
int nQueens(int n) {
// write code here
N=n;
dfs(0);
return cnt;
}
void dfs(int i)
{
if(i==N&&i!=0)//到达最后一行,注意0是特殊数据
{
cnt++;//计数
return;
}
for(int j=0;j<N;j++)//在这一行的每一列放皇后
{
if(col[j]||dpos[i+j]||dneg[i-j+N-1])continue;//有别的皇后能攻击到就忽略这个位置
col[j]=dpos[i+j]=dneg[i-j+N-1]=1;//占领这些相应的列和左下对角线和右下对角线
dfs(i+1);//到下一行
col[j]=dpos[i+j]=dneg[i-j+N-1]=0;//拿掉这行的皇后,取消相应的占领
}
}//运行到这说明该行放置皇后失败,不计数返回
}; import java.util.*;
public class Queens {
public int nQueens(int n) {
int[] row = new int[n];
return process(row,n,0);
}
public int process(int[] row,int n, int rowNum){
int sum = 0;
if(rowNum==n){
return 1;
}
for(int j=0;j<n;j++){
if(isValid(row,rowNum,j)){
row[rowNum]=j;
sum +=process(row,n,rowNum+1);
}
}
return sum;
}
public boolean isValid(int[] row,int x,int y){
for(int rowNum=0;rowNum<x;rowNum++){
int col = row[rowNum];
if(col==y) return false;
if(Math.abs(rowNum-x)==Math.abs(col-y)) return false;
}
return true;
}
} class Queens {
public: int cnt = 0; bool F(int r, int *cols){ for(int i=0;i<r;i++) if(cols[i]==cols[r] || abs(cols[i]-cols[r])==abs(i-r)) return false; return true; }
void DFS(int r, int n, int *cols){
if(r==n)
cnt++;
else{
for(int i=0;i<n;i++){
cols[r] = i+1;
if(F(r,cols))
DFS(r+1,n,cols); } } }
int nQueens(int n) {
int cols[n],r=0;
for(int i=0;i<n;i++)
cols[i] = 0;
DFS(r,n,cols);
return cnt;
}
};
int nQueens(int n) {
int ans = 0;
vector<int> chessBorad(n + 1);
count(chessBorad, 1, n, ans);
return ans;
}
void count(vector<int> &chessBorad, int row, int n, int &ans) {
if (row > n) {
ans++;
return;
}
for (int col = 1; col <= n; col++) {
chessBorad[row] = col; //row是行,判断(row,chessBorad[row](== col))位置可否放旗子
if (place(chessBorad, row)) { //如果可以放置,就进行下一行的放置,不能就将row行棋子放到下一列
count(chessBorad, row + 1, n, ans);
}
}
}
bool place(vector<int> &chessBorad, int currentRow) {
for (int previousRow = 1; previousRow < currentRow; previousRow++) { //枚举已放置的前previousRow行,看这一行能否放置
if (chessBorad[previousRow] == chessBorad[currentRow] || //同一列
chessBorad[previousRow] - chessBorad[currentRow] == previousRow - currentRow || //右对角线
chessBorad[previousRow] - chessBorad[currentRow] == currentRow - previousRow) { //左对角线
return false; //如果在同一列,右对角线,左对角线则不能放置
}
}
return true;
}
class Queens {
public:
int total = 0;
int nQueens(int n) {
int temp[n]; // 下标为行,值为列值
for(int i=0; i<n; i++){
temp[i] = 0;
}
int cur = 0;
calc(n, cur, temp);
return total;
}
//
void calc(int n, int cur, int temp[]){
if(n == cur){
total++;
}else{
for(int i=0; i<n; i++){ // 每一次都可能去每一行
temp[cur] = i+1;
if(judge(cur, temp)){
calc(n, cur+1, temp); // 这里有回溯的思想
}
}
}
}
// 判断是否在两条对角线上,是否在同一列中
bool judge(int cur, int temp[]){
for(int i=0; i<cur; i++){
if(temp[i] == temp[cur] || (temp[i]-temp[cur])==(i-cur) || (temp[i]-temp[cur])==(cur-i)){
return false;
}
}
return true;
}
};
import java.util.*;
public class Queens {
public int nQueens(int n) {
if (n<0) return 0;
// write code here
int[] record = new int[n];
return process(0, record, n);
}
private 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)){
record[i] = j;
res += process(i+1, record, n);
}
}
return res;
}
private boolean isValid(int[] record, int i, int j){
for (int k=0; k<i; k++){
// 若在同一列或者对角线则返回false
if (j == record[k] || Math.abs(record[k] - j) == Math.abs(k - i)) return false;
}
return true;
}
}
//开辟一维数组记录摆放皇后的位置:
public int nQueens(int n) {
this.n = n;
A = new int[n];
return f(0);
}
int cnt, n, A[];
int f(int i) {
if (i >= n) {
return cnt++;
}
for (int j = 0; j < n; j++) {
A[i] = j;
if (check(i,j)) {
f(i+1);
}
}
return cnt;
}
boolean check(int x, int y) {
for (int i = 0; i < x; i++) {
if (A[i] == y || x- i == Math.abs(y-A[i])) //检查同列和对角线
return false;
}
return true;
}
//开辟二维数组记录棋盘,采用回溯法:
public int nQueens(int n) {
this.n = n;
A = new boolean[n][n];
f(0);
return cnt;
}
int cnt = 0, n;
boolean A[][];
void f(int i) {
if (i >= n) {
cnt++;
return;
}
for (int j = 0; j < n; j++) {
A[i][j] = true;
if (check(i,j)) {
f(i+1);
}
A[i][j] = false;
}
}
//啰嗦一点,需要向四个方向扫描
boolean check(int x, int y) {
for (int i = 0; i < n; i++) {
if (i != x && A[i][y] == true) {
return false;
}
}
for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) {
if (A[i][j] == true)
return false;
}
for (int i = x - 1, j = y + 1; i >= 0 && j < n; i--, j++) {
if (A[i][j] == true)
return false;
}
for (int i = x + 1, j = y - 1; i < n && j >= 0; i++, j--) {
if (A[i][j] == true)
return false;
}
for (int i = x + 1, j = y + 1; i < n && j < n; i++, j++) {
if (A[i][j] == true)
return false;
}
return true;
}
class Queens {
public:
int nQueens(int n) {
// write code here
if(n<=0) return 0;
int* arr=new int[n];
for(int i=0;i<n;i++)
arr[i]=i;
int g_number=0;
helper(arr,n,0,g_number);
return g_number;
}
void helper(int column[],int length,int index,int& g_number)
{
if(index==length)
{
if(checkVaild(column,length))
g_number++;
}
else
{
for(int i=index;i<length;i++)
{
swap(column[index],column[i]);
helper(column,length,index+1,g_number);
swap(column[index],column[i]);
}
}
}
bool checkVaild(int column[],int length)
{
int i,j;
for(i=0;i<length;i++)
{
for(j=i+1;j<length;j++)
{
if((i-j==column[i]-column[j])||(j-i==column[i]-column[j]))
return false;
}
}
return true;
}
};
class Queens {
public:
typedef pair<double, double> Pair;
int res;
bool checkAttack(int x, int y, vector<Pair>& place)
{
if (place.empty()) return false;
for (auto& pr : place)
{
if (x == pr.first || y == pr.second || abs(x - pr.first) == abs(y - pr.second))
return true;
}
return false;
}
void DFS(int n, int level, vector<Pair>& place)
{
if (level >= n) ++res;
for (int i = 0; i < n; ++i)
{
if (!checkAttack(level, i, place))
{
place.emplace_back(level, i);
DFS(n, level + 1, place);
place.pop_back();
}
}
}
int nQueens(int n)
{
res = 0;
vector<Pair> place;
place.reserve(n);
DFS(n, 0, place);
return res;
}
};
# -*- coding:utf-8 -*- class Queens: def nQueens(self, n): result = [0] * n results = [] n_row = 0 while n_row < n: pos = self.findLegalPosition(result, n_row, n) # print pos if pos is not None: result[n_row] = pos if n_row == n - 1: results.append(result[:]) if pos is None or n_row == n - 1: while 1: n_row -= 1 if n_row < 0: print results return len(results) pos = self.findLegalPosition(result, n_row, n, back_tracing=True) if pos: result[n_row] = pos break n_row += 1 def findLegalPosition(self, arr, n_row, n, back_tracing=False): start = 0 if back_tracing: start = arr[n_row] + 1 for col in range(start, n): ok = True for row in range(n_row): if arr[row] == col: ok = False break if n_row - row == abs(col - arr[row]): ok = False break if ok: return col return None
/*
思路:回溯法 深度搜素
n皇后要求:
1.同一行只有一个皇后
判断是否在同一 行:(x1,y1)(x2,y2) 当 x1 == x2 说明在同一 行
2.同一列只有一个皇后
判断是否在同一 列:(x1,y1)(x2,y2) 当 y1 == y2 说明在同一 列
3.同一 撇 只有一个皇后
判断是否在同一 撇:(x1,y1)(x2,y2) 当 x1+y1 == x2+y2 说明在同一 撇
4.同一 捺 只有一个皇后
判断是否在同一 捺:(x1,y1)(x2,y2) 当 x1-y1 == x2-y2 说明在同一 撇
解题方法:
1.遍历数组的每个位置,把当前位置和已知符合要求的坐标进行比较。
2.如果合法:添加当前坐标。否则,放弃该坐标。
3.如果遍历完一行都没有一个合法位置,该策略废弃,回退。
*/
class Queens {
public:
int result=0;
//判断该位置是否合法
bool IsLegal(vector<pair<int,int>>& way,int x,int y){
for(int i=0;i<way.size();i++){
//判断是否在同一行 或 同一列
if((way[i].first == x) || (way[i].second==y)){
return false;
}
//判断是否在统一 捺
if((way[i].first-way[i].second)==(x-y)){
return false;
}
//判断是否在同一 撇
if((way[i].first+way[i].second)==(x+y)){
return false;
}
}
return true;
}
//递归搜索函数
// n:总的皇后数量 index 当前行号
void DFS(int n,int index,vector<pair<int,int>> way){
//搜索完毕
if(n == index){
return;
}
for(int j=0;j<n;j++){
vector<pair<int,int>> temp = way;
//判断该位置是否合法
bool isl = IsLegal(temp,index,j);
if(isl){
//位置合法,添加
temp.push_back(make_pair(index,j));
if(temp.size()==n){
//已经存储了n个皇后,该条路径搜索完毕
result++;
//腾出位置供本行下一个位置使用
temp.pop_back();
}else{
//搜索的皇后数量不足,去下一行继续搜索
DFS(n,index+1,temp);
//腾出位置供本行下一个位置使用
temp.pop_back();
}
}
}
}
int nQueens(int n) {
if(n<=1){
return n;
}
vector<pair<int,int>> way;
DFS(n,0,way);
return result;
}
}; import java.util.*;
public class Queens {
public int nQueens(int n) {
Op op = new Op();
op.dfs(0,n);
return op.result;
}
static class Op{
boolean[] cols = new boolean[66];
boolean[] diag = new boolean[66];
boolean[] cdiag = new boolean[66];
int result ;
void dfs(int row,int n) {
if(row == n) {
++result;
return;
}
//尝试
for(int i=0;i< n;++i) {
if(cols[i]==false && diag[i+row+n] ==false && cdiag[i-row + n]==false) {
//这个列可以放
cols[i] = true;
diag[i+row+n] = true;
cdiag[i-row +n] = true;
dfs(row+1,n);
cols[i] = false;
diag[i+row+n] = false;
cdiag[i-row +n] = false;
}
}
}
}
} class Queens {
public:
int nQueens(int n) {
// write code here
memset(queen, 0, sizeof(queen) );
int i = 1;
queen[1] = 0;
while (i >= 1) {
queen[i] += 1;
while (queen[i] <= n && !couldPlace(i) ) {
++queen[i];
}
if (queen[i] <= n) {
if (i == n) {
++methods;
} else {
++i;
queen[i] = 0;
}
} else {
--i;
}
}
return methods;
}
private:
bool couldPlace(int i) {
for (int j = 1; j < i; ++j) {
if (queen[j] == queen[i] ||
abs(j - i) == abs(queen[j] - queen[i]) ) {
return false;
}
}
return true;
}
static const int N = 16;
int queen[N] = {0};
int methods = 0;
}; class Queens {
int count=0;
public:
int nQueens(int n) {
// write code here
nqueen(0,n,0,0,0);
return count;
}
void nqueen(int row,int n,int straight_line,int r_line,int l_line)
{ //左斜线,右斜线,直线进行判断
if(row==n)
{
count++;
}
else
{
int bit=(straight_line|r_line|l_line)&((1<<n)-1)^((1<<n)-1);//bit中1就是可以放,0是不可以
while(bit)
{
int b=bit&-bit;//取最右边的第一个1
nqueen(row+1,n,straight_line|b,(r_line|b)>>1,(l_line|b)<<1);
bit&=(bit-1);//把最右边的最后一个1变成0,防止重复
}
}
}看不懂可以留言,我给链接
};