问题引入:
八皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
思路:dfs,按照一行到n行顺序放入,判断皇后在列的位置是否合法(写一个函数判断当前皇后所在位置的行和列还有两条对角线上是否存在其他的皇后,若不存在则合法),若不合法,找下个位置,若合法,dfs下一行,当达到终点时,结果加一。
Check函数检查对角线时的规律:
右上对角线:横竖坐标的和为一定值,例:4+1=5,3+2=5,2+3=5,1+4=5......
1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 |
2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 |
3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 |
4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 |
5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 |
6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 |
7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 |
8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 |
右下对角线:横竖坐标的差为一定值,例:2-1=1,3-2=1,4-3=1,5-4=1......
1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 |
2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 |
3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 |
4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 |
5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 |
6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 |
7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 |
8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 |
C++代码:
#include <iostream>
using namespace std;
int Map[15];//Map[i]表示第i排存放的皇后
int N;
int res;
bool Check(int m,int n)//检查位置Map[m][n]是否能放皇后
{
for(int i=1;i<=m;i++)
{
if(Map[i]==n)//检查列
return false;
if(i+Map[i]==m+n)//检查左对角线
return false;
if(i-Map[i]==m-n)//检查右对角线
return false;
}
return true;
}
void dfs(int a)
{
if(a>N)//a==n+1,a==n时还为选完
{
res++;
return;
}
for(int i=1;i<=N;i++)//遍历列
{
if(Check(a,i))
{
Map[a]=i;
dfs(a+1);
Map[a]=0;//复原
}
}
}
int main()
{
// 请在此输入您的代码
cin>>N;
dfs(1);
cout<<res;
return 0;
}
希望对有需要的人能有所帮助,欢迎大家有什么问题到评论区里一起讨论!