问题描述
在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;
}