八皇后是国际象棋中最大的棋子,要使得放置N个皇后在N*N的棋盘上,使其不能互相攻击
皇后攻击范围:其同行,同列 以及其斜对角。
回溯法,把一个皇后放在某行的第一列,然后检查它是否与棋盘上的其他皇后互相攻击,如果存在互相攻击,函数把皇后移动到该行的第二列再进行检查,如果每列都存在相互攻击的局面,函数就该返回。
但是如果皇后可以放在这个位子,函数借着应该递归地调用自身,把一个皇后放在下一行,当递归调用返回时,函数再把原先那个皇后移到下一列。当皇后成功地放置于最后一行时,打印出棋盘,显示8个皇后的位子。
#include<stdio.h>
#include <math.h>
#define Num_Queen 8//这里定义为8个皇后 可任意修改
int state[Num_Queen];//第M行的第几个位有皇后,例如state[4]=3;表示第四行第三列有皇后;
int sum = 0;
//判断各个皇后大人是否相互攻击
int attack( int n)
{
for(int i =0;i<n;i++)
{
if(state[i] == state[n])//判断是否在同一列
{
return 0;
}
if(abs(state[n]-state[i])==abs(n-i))//判断是否在对角线
{
return 0;
}
}
return 1;
}
//打印棋盘,有皇后的位置打印出“*”,空格则打印“#”
void output()
{
for(int i = 0;i<Num_Queen;i++)
{
for(int j = 0;j<Num_Queen;j++)
{
if(j == state[i])
{
printf("*");
}
else
{
printf("#");
}
}
printf("\n");
}
printf("\n\n");
}
//回溯函数,递归放置N个皇后
void queen(int n)
{
if(n == Num_Queen)//如果8个皇后都放好切不互相攻击的话,将它输出并回溯
{
sum++;//计算共有多少种放置方法
output();
return;
}
for(int i = 0;i<Num_Queen;i++)
{
state[n] = i;//在n行i列上放置皇后
if(attack(n)) //如果没有互相攻击的话,则进行下一行的试探
{
queen(n+1);
}
}
}
int main()
{
queen(0);//从第0行开始递归
printf("%d\n",sum);
return 0;
}