N皇后问题
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。
DFS+回溯
- 二维矩阵chess[N][N]代表棋盘,行列对角线上不能有其他Queen
- 可选择遍历每行(列),每行(列)找一个可以放置Queen的位置
- 失败即可回溯重新找
#include <iostream>
using namespace std;
#define N 8
int chess[N][N];
int count;
//因为我是以行递增去增加Queen,
//所以可以保证行上不会多于一个Queen
bool check(int row,int j){
if(row==0){
return true;
}else{
for(int i=0;i<row;i++){
//判断同列上是否有其他Queen
if(chess[i][j]==1){
return false;
}
//判断左上对角线是否有其他Queen
if(j-row+i>=0&&chess[i][j-row+i]==1){
return false;
}
//判断左下对角线是否有其他Queen
if(j+row-i<N&&chess[i][j+row-i]==1){
return false;
}
}
}
return true;
}
void print(){
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
cout<<chess[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
void dfs(int row){
if(row>=N){
count++;
//需要输出则调用print函数
//print();
return;
}
for(int j=0;j<N;j++){
for(int y=0;y<N;y++){
chess[row][y]=0;//清洗当前行 ,因为上一次循环中为这行赋过一个值
}
if(check(row,j)){
chess[row][j]=1;
dfs(row+1);
chess[row][j]=0;
}
}
}
int main() {
count=0;
dfs(0);
cout<<"sum is "<<count<<endl;
return 0;
}
全排列
- 1到N的全排列,排列下标表示棋盘横坐标,排列中的数字代表棋盘纵坐标
- 只需判断对角线上的其他点就好了
#include <iostream>
using namespace std;
#define N 8
int ans[N],mask[N],count;
void print(){
int flag=1;
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
if((i-j==ans[i]-ans[j])||(i-j==ans[j]-ans[i])){
flag=0;
return;
}
}
}
if(flag){
count++;
for(int i=0;i<N;i++){
cout<<ans[i];
}
cout<<endl;
}
}
void dfs(int num){//j cols
if(num==N){
print();
return;
}
for(int j=0;j<N;j++){
if(mask[j]==0){
mask[j]=1;
ans[num]=j+1;
dfs(num+1);
ans[num]=0;
mask[j]=0;
}
}
}
int main() {
count=0;
dfs(0);
cout<<"sum is "<<count<<endl;
return 0;
}