问题描述:在一个8*8的国际象棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列和同一斜线上,问有多少种摆法。
思路:因为每行、每列都只能有一个皇后,因此可以按照行来看,对每行皇后所在的列做一个标记。
每个后可以按照行来看,那么每个列数可以看作一个全排列。上图所表示的全排列为:62714853
下面结合代码和注释讲解具体实现过程:在这里插入代码片
#include<stdio.h>
int num[9],book[9],count;
//num数组给1-8做标记,i已被使用num[i]标记为1
//book数组存储全排列,book[k]表示第k行放的皇后的列
//count计算方法数
void fun(int x)//1-8的全排列并判断是否符合要求
{
if(x==9){
bool flag=true; //flag标记全排列是否符合要求
int hash1[17]={0},hash2[17]={0},hash3[17]={0};
for(int k=1;k<=8;k++)
{
hash1[k+book[k]]++; //是否有多于1个皇后在同一左斜线上
if(k>book[k]){ //提醒:k-book[k]可正可负可为零,需分成k>book[k]和k<=book[k]
hash2[k-book[k]]++;//是否有多于1个皇后在同一右斜线上
}else{
hash3[book[k]-k]++;//是否有多于1个皇后在同一右斜线上
}
}
for(int i=2;i<=16;i++)
{
if(hash1[i]>1)
flag=false; //有多于一个皇后处于同一左斜线上,不符合
}
for(int j=0;j<=8;j++)
{
if(hash2[j]>1||hash3[j]>1)
{
flag=false; //有多于一个皇后处于同一右斜线上,不符合
}
}
if(flag){
count++;
for(int i=1;i<=8;i++)
{
printf("%d",book[i]);
}
printf("\n");
}
}
else{ //DFS思想实现全排列
for(int j=1;j<=8;j++){
if(num[j]==0){
num[j]=1;
book[x]=j;
fun(x+1);
num[j]=0;
}
}
}
}
int main()
{
fun(1);
printf("%d\n",count);
return 0;
}
注:以上代码实现了将所有符合要求的全排列输出,并输出方法数。