八皇后问题是一个经典的回溯算法问题,目标是在8x8的棋盘上放置8个皇后,使得任何两个皇后之间都不存在威胁(即任何两个皇后都不能在同一行、同一列或同一斜线上)。
1、理思路
由于皇后的位置特殊性导致如果通过常规算法会带来的时间复杂度的提高,不妨看以下思路:
行为i,列为j,每个单元格对应为(i+j),再通过寻找从左上到右下的对角线表达式为
(j-i-2*8);
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -9 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -10 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -11 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -12 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -13 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -14 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -15 |
-23 | -22 | -21 | -20 | -19 | -18 | -17 | -16 |
同时从右上到左下的对角线表达式为(i+j);
可得代码思路。
2、写代码
#include <bits/stdc++.h>
using namespace std;
int a[50],b[50],c[50],n;
char ans[10][10];
bool f()
{
for(int i=1;i<=8;i++)
{
if(a[i]==0) return 0;
}
return 1;
}
void dfs(int i)
{
for(int j=1;j<=8;j++)
{
if(a[j]==0&&b[i+j]==0&&c[(j-i-2*8)*(-1)]==0)
{
if(i==8)
{
a[j]=1;
if(f()==0) return;
cout<<"Situation "<<(++n)<<":"<<endl;
ans[i][j]='Q';
for(int x=1;x<=8;x++)
{
for(int y=1;y<=8;y++)
{
cout<<ans[x][y];
}
cout<<endl;
}
a[j]=0;
ans[i][j]='.';
cout<<endl;
return;
}
a[j]=1;
b[i+j]=1;
c[(j-i-2*8)*(-1)]=1;
ans[i][j]='Q';
dfs(i+1);
a[j]=0;
b[i+j]=0;
c[(j-i-2*8)*(-1)]=0;
ans[i][j]='.';
}
}
}
int main()
{
for(int i=1;i<=8;i++)
{
for(int j=1;j<=8;j++)
{
ans[i][j]='.';
}
}
dfs(1);
return 0;
}
3、结果
解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。
4、拓展
当然随便改一下便可变成“m皇后”问题(m的范围不给出了)
#include <bits/stdc++.h>
using namespace std;
int a[500],b[500],c[500],n,m;
char ans[200][200];
bool f()
{
for(int i=1;i<=m;i++)
{
if(a[i]==0) return 0;
}
return 1;
}
void dfs(int i)
{
for(int j=1;j<=m;j++)
{
if(a[j]==0&&b[i+j]==0&&c[(j-i-2*m)*(-1)]==0)
{
if(i==m)
{
a[j]=1;
if(f()==0) return;
cout<<"Situation "<<(++n)<<":"<<endl;
ans[i][j]='Q';
for(int x=1;x<=m;x++)
{
for(int y=1;y<=m;y++)
{
cout<<ans[x][y];
}
cout<<endl;
}
a[j]=0;
ans[i][j]='.';
cout<<endl;
return;
}
a[j]=1;
b[i+j]=1;
c[(j-i-2*m)*(-1)]=1;
ans[i][j]='Q';
dfs(i+1);
a[j]=0;
b[i+j]=0;
c[(j-i-2*m)*(-1)]=0;
ans[i][j]='.';
}
}
}
int main()
{
cin>>m;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
ans[i][j]='.';
}
}
dfs(1);
return 0;
}
感谢观看。