程序分析:在8*8的棋盘上安置八个皇后且相互不能攻击。
一个皇后的攻击范围如下图所示:
其中一种摆法如下:
C++代码:
方法一:
#include <iostream>
using namespace std;
const int ArSize = 8;//这个数等于几,就是几皇后。
int num = 0;
bool check(bool arr[ArSize][ArSize], int row, int column){
// 判断皇后的落点是否合规
if (row == 0){
return true;
}
int i, j;
for (i = 0; i < row; ++i){
// 判断纵向是否有冲突
if (arr[i][column]){
return false;
}
}
i = row - 1;
j = column - 1;
while (i >= 0 && j >= 0){
// 判断正斜对角线是否有冲突
if (arr[i][j]){
return false;
}
--i;
--j;
}
i = row - 1;
j = column + 1;
while (i >= 0 && j <= ArSize - 1){
// 判断负斜对角线是否有冲突
if (arr[i][j]){
return false;
}
--i;
++j;
}
return true;
}
void outPut(bool arr[ArSize][ArSize]){
// 打印每种正确的解法
++num;
cout << "**********************" << num << "*********************" << endl;
for (int i = 0; i < ArSize; ++i){
for (int j = 0; j < ArSize; ++j){
cout << arr[i][j] << " ";
}
cout << endl;
}
cout << "*********************************************" << endl;
}
void solve(bool arr[ArSize][ArSize], int row) {
// 回溯法
for (int column = 0; column < ArSize; ++column) {
arr[row][column] = true;
if (check(arr, row, column)) {
if (row + 1 == ArSize) {
outPut(arr);
}
else {
solve(arr, row + 1);
}
}
arr[row][column] = false;
}
}
int main()
{
bool chessboard[ArSize][ArSize];
// 数组初始化
for (auto &i : chessboard){
for (auto &j : i){
j = false;
}
}
/*
//数组初始化方法二
for (int i = 0; i < ArSize; i++) {
for (int j = 0; j < ArSize; j++) {
chessboard[i][j] = false;
}
}
*/
solve(chessboard, 0);
cout << "八皇后问题共有" << num << "种解!" << endl;
system("pause");
return 0;
}
方法二:
#include<iostream>
#include<vector>//用向量保存皇后
using namespace std;
class Queen {
public:
short x;
short y;
Queen(short _x, short _y) :x(_x), y(_y) {}
bool Attack(Queen &queen) {
//能相互攻击返回true
return x == queen.x || x - y == queen.x - queen.y || x + y == queen.x + queen.y || y == queen.y;
}
};
void PrintQueens(vector<Queen> &v,int *count) {
cout << "第" << *count << "种摆法:" << endl;
short i, j;
vector<Queen>::iterator itr1 = v.begin();
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
if (itr1 != v.end()&&i == itr1->y&&j == itr1->x) {
cout << "后";
itr1++;
}
else {
cout << "□";
}
}
cout << endl;
}
(*count)++;
}
int main() {
vector<Queen> vt;
short i, j;
vector<Queen>::iterator itr;//迭代器
Queen *q;
int count=1;
for (i = 0; i < 8; i++) {
j = 0;
Repeat:
for (; j < 8; j++) {
q = new Queen(j, i);
for (itr = vt.begin(); itr != vt.end(); itr++) {
if (q->Attack(*itr)) {
//新皇后与原来的皇后进行攻击测试
delete q;
break;
}
}
if (itr == vt.end()) {
//新皇后与原来皇后不冲突
vt.push_back(*q);
delete q;
if (vt.size() == 8) {
PrintQueens(vt, &count);//输出八皇后解法
j = 8;//人为赋值,使流程进入 if(j==8)回溯重试
}
break;//退出列遍历,直接到下一行的第一列
}
}
if (j == 8) {
//当前的一整行都无法安放皇后
if (vt.back().x == 7) {
//向量尾部的皇后若刚好是当前行最后一列的位置,不能将x后移,必须多弹出一次
vt.pop_back();//弹出
}
if (!vt.empty()) {
i = vt.back().y;
j = vt.back().x + 1;
vt.pop_back();
goto Repeat;
}
}
}
return 0;
}
C++运行结果:
方法一:
方法二: