N皇后问题(n > 3):
简述:这道题用到了回溯法,熟悉下递归回溯
解决难点:
1) 由于使用的是一维数组表示地图信息,所以用到了x = index % width 、y = index / width
2) 在回溯过程中,保证回来的时候,地图信息要保留原先的状况,这里我用了两个数组saveLegal[] 和saveMap[]记录了加入n -1个皇后前的地图信息,在函数从n - 1个皇后回溯到n时可以还原legal[] 和 map[]数组的状态,这步骤很重要!
3)还有就是判断皇后之间是否冲突,这个用legal[]数组标记不可摆放位置,那么放下一个皇后的时候就别放在这些legal[]为false的点上
代码:
/***********************N_Queen问题*************************/
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
static bool *legal; //记录不可摆放位置
static bool *map; //记录摆放皇后的位置
static int width; //地图初始的宽度,就是皇后的数目
void Intialize(int n){
width = n;
legal = new bool[width * width];
for(int i = 0;i < width * width;i++){
legal[i] = true;
}
map = new bool[width * width];
for(int i = 0;i < width * width;i++){
map[i] = false;
}
}
//这里x、y的坐标以是到(0,0)的距离
int GetX(int num,int width){
return num % width;
}
int GetY(int num,int width){
return num / width;
}
//从在n行,i列放下某个皇后之后,需要把后面n-1个皇后不能放的位置标记出来
void setFalse(int n,int i){
int index = n * width + i;
//横向置为false
for(int j = 0;j < width;j++){
legal[n * width + j] = false;
}
//纵向置为false
for(int j = 0;j < width;j++){
legal[j * width + i] = false;
}
//45度斜线置为false
for(int j = 0;j < width * width;j++){
if((GetX(j,width) + GetY(j,width)) == (GetX(index,width) + GetY(index,width))){
legal[j] = false;
}
}
//135度斜线置为false
for(int j = 0;j < width * width;j++){
if((GetX(j,width) - GetY(j,width)) == (GetX(index,width) - GetY(index,width)))
legal[j] = false;
}
}
//具体摆放的代码,从第N个皇后进行摆放到1结束
static int cnt = 1; //记录第几组结果
void LayQueen(int n){
if(n == 0){
cout <<"第" << cnt++ << "组:" << endl;
for(int i = 0;i < width * width;i++){
if(map[i]){
int height = i / width;
cout << "(" << (i % width) << "," << height << ") ";
}
}
cout << "\nMap: " << endl;
for(int i = 0;i < width * width;i++){
if(map[i])
cout << "1 ";
else
cout << "0 ";
if(i % width == width - 1)
cout << endl;
}
cout << "\n\n";
}else{
for(int i = 0;i < width;i++){
//第n个放在n-1行,每个位置都试过去,得到所有情况
if(legal[(n - 1) * width + i]){
/*
* *********用来存放放置n - 1个皇后前的状态****************/
bool *saveLegal = new bool[width * width];
for(int j = 0;j < width * width;j++){
saveLegal[j] = legal[j];
}
bool *saveMap = new bool[width * width];
for(int j = 0;j < width * width;j++)
saveMap[j] = map[j];
/********************************************
* */
//修改可放置皇后位置后,设置不合法位置setFalse放入下一个皇后
map[(n - 1) * width + i] = true; //放下(i,n-1)皇后
setFalse(n - 1,i); // 第一行是0行 所以带入n - 1行, i列 皇后位置为(n-1,i)
LayQueen(n - 1);
//
/*
* *************还原放置n - 1个皇后前的状态****************/
for(int j = 0;j < width * width;j++)
legal[j] = saveLegal[j];
for(int j = 0;j < width * width;j++)
map[j] = saveMap[j];
delete []saveLegal;
delete []saveMap;
/********************************************
* */
}
}
}
}
int main(){
int NumOfQueen = 8;
Intialize(NumOfQueen);
LayQueen(NumOfQueen);
return 0;
}
输出(只截取了部分):