N皇后摆放问题

博客围绕N皇后问题展开,该问题是在8×8格国际象棋上摆8个皇后,使其不能互相攻击。作者分享了用C++和C语言解决此问题的代码,还提到递归回溯方法,可看到1 - 15皇后的解法,也介绍了自己的普通方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
在这里插入图片描述
这是读书时写的从C++ 的代码,发现这个还是挺有意思的,没事又搞了搞,其实没啥说的直接上代码吧。

1、C++

#include <iostream>
#include <cmath>
using namespace std;
int N;
int queenPos[100];//存放k个元素的位置,即行号,k就是列号,
void NQueen(int k);
int main() {
	cin >> N;//这里将8皇后拓展为N皇后
	NQueen(0);
	system("pause");
	return 0;
}
void NQueen(int k) {//在0~k-1行皇后已经摆好的情况下,摆第k行及其后的皇后
	int i;
	if (k == N) {//N个皇后已经摆好,也就是基例,结束条件
		for (i = 0; i < N; i++)
			cout << queenPos[i] + 1 << ' ';
		cout << endl;
		return;
	}
	for (i = 0; i < N; i++) {//逐个尝试第k个皇后的位置
		int j;
		for (j = 0; j < k; j++) {//与已经摆好的K个皇后的位置比较,看是否冲突
			if (queenPos[j] == i || abs(queenPos[j] - i) == abs(k - j)) {//处于同一行或者斜对角(行差和列差的绝对值相等)
				break;//冲突,测试下一个
			}
		}
		if (j == k) {//当前选的位置i不冲突
			queenPos[k] = i;//将第k个皇后放在位置i
			NQueen(k + 1);//递归下一个
		}
	}
}

2、C语言

先来膜拜下大神的代码。想弄懂拆分下。递归回溯
1、

#include <stdio.h>                                                                                                              

int queen(int l,int r,int m,int i,int j,int k){
         return j?i?queen(l,r,m,i&i-1,1,k)+queen((l|i&-i)*2,(r|i&-i)/2,m|i&-i,0,0,k-1):0:k?queen(l,r,m,~(l|r|m)&255,1,k):1;
}
void main(void){
         printf("%d\n",queen(0,0,0,0,0,8));
}

2、

		   q
     (l,r,m,n,i,j)
        {return
        j?i?q(l,
         r,m,n,
      i&i-1,1)+q((
       l|i&-i)*2
        ,(r|i&-
         i)/2,
        m|i&-i,
        n,0,0):
         0:m==
         n?1:q
         (l,r,
         m,n,~
        (l|r|m)
      &n,1);}main
     (n){for(n=0;n
  ++<15;)printf("%d "
,q(0,0,0,(1<<n)-1,0,0));}

执行gcc -w -include stdio.h queen1.c && ./a.out
可以看到1-15皇后的解法。

普通人方法(我的方法):

#include<stdio.h>

#define TRUE 0
#define FALSE -1

int queen[8]={0};//用来储存queen位置
int count=0;//用来统计可行方案
int available(int current,int next){//判断后面皇后是否与已排放皇后冲突
	for(int i = 0;i < current;i++){
		if(next == queen[i]) return FALSE;//同一列拒绝
		if((current - i) == (next - queen[i])) return FALSE;//同一主对角线拒绝
		if((current - i) + (next - queen[i]) == 0) return FALSE;//同一副对角线拒绝
	}
	return TRUE;
}
void findSpace(int queenNumber){ //先将queen放在queenNumber的位置
	for(int i = 0;i < 8;i++){//从0~7遍历这一行的八个空位
		if(TRUE == available(queenNumber,i)){//如果可以放这个位置就记录下第queenNumber个皇后的位置
			queen[queenNumber] = i;
			if(queenNumber == 7){
				count++;//八皇后都放好统计一下
				return;
			}
			int nextNumber = queenNumber + 1;//还有皇后没放递归放下一个皇后
			findSpace(nextNumber);
		}
	}
	queen[--queenNumber] = -1;//如果这一行没有可放的位置说明上一行皇后放的位置不行,要为上一个皇后寻找新的可放位置
	return;
}
int main(void){

	findSpace(0);//从0开始递归
        printf("%d\n",count);	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值