Решение

Чтобы решить проблему Восьми Королев, мы используем алгоритм отслеживания в обратном порядке. Алгоритм включает размещения королев, столбец за столбцом, на шахматную доску. Алгоритм завершается, когда он размещает все восемь королев на доску без атакующих друг друга. Алгоритм отслеживает в обратном порядке, когда он достигает ситуации, куда новая королева не может быть размещена в плату, не атакуя королеву уже на плате. Когда алгоритм достигает этой ситуации, он передвигает фигуру, которую он последний раз добавил на доске к другому расположению. Идея здесь, это передвигая фигуры создать комбинацию, которая позволяет алгоритму добавлять как можно больше фигур. Например, рассмотрите шахматную доску на рисунке 6. Здесь, мы разместили семь королев успешно в первые семь столбцов так, что, никакие две королевы не атакуют друг друга. Мы должны отследить в обратном порядке, однако, так как никакое пространство в столбце для восьмой не существует, куда мы можем разместить восьмую королеву.


Рисунок 6, Seven queens placed, but we must backtrack

Часть отслеживания в обратном порядке алгоритма тогда попыталась бы переместить седьмую королеву в другое пятно в седьмом столбце, чтобы открыть пятно в восьмом столбце для восьмой королевы. Если седьмая королева не может быть перемещена, потому что никакие другие пробелы не существуют в столбце семь, алгоритм должен удалить ту королеву и поддержать и рассмотреть перемещение королевы в столбце шесть. В конечном счете, алгоритм повторяет этот процесс размещения королев, и поддержка вплоть до этого находит комбинацию, которая решает проблему.

Вышеупомянутая реализация проблем Восьми Королев выводит первое решение, которое это находит и затем завершает. Как осуществление, можно расширить это, чтобы найти и вывести на экран все возможные решения?

queens.cpp Queenboard.h #include <iostream> #include <cstdlib> #include <stdexcept>   #include "Queenboard.h"   using namespace std;   bool place_queens(Queenboard& qb, int col);   int main(int argc, char* argv[]) {   try {   Queenboard qb; if (! place_queens(qb, 0)) { cout << "No solution found. "; } return EXIT_SUCCESS; } catch (exception& e) { cerr << e.what() << " "; } catch (...) { cerr << "Unknown exception caught. "; }   return EXIT_FAILURE; }   bool place_queens(Queenboard& qb, int col) {   bool inserted = false; for (int row = 0; row < BOARDSIZE; row++) {   if (! qb.is_space_under_attack(row, col)) {   // insert a queen qb.occupy_space(row, col); inserted = true;   if (col == BOARDSIZE - 1) { // solution found! cout << qb << " "; return true;   } else { // place a queen in the next column if (place_queens(qb, col + 1)) { return true; } else { inserted = false; } } } }   if (! inserted) { // backtrack to previous column qb.clear_column(col - 1); return false; } } #ifndef _QUEENBOARD_H_ #define _QUEENBOARD_H_   const int BOARDSIZE = 8;   using namespace std;   class Queenboard {   private: bool board[BOARDSIZE][BOARDSIZE];   public: Queenboard(); bool is_space_under_attack(int, int) const; void occupy_space(int, int); void clear_column(int);   friend ostream& operator<<(ostream& out, const Queenboard& cb); };   Queenboard::Queenboard() { // Initialize the board to contain zero queens. for (int row = 0; row < BOARDSIZE; row++) { for (int col = 0; col < BOARDSIZE; col++) { board[row][col] = false; } } }     ostream& operator<<(ostream& out, const Queenboard& cb) {   // output the board for (int row = 0; row < BOARDSIZE; row++) {   out << "---------------------------------" << endl; for (int col = 0; col < BOARDSIZE; col++) { out << "|"; if ( cb.board[row][col]) { out << " Q "; } else { out << " "; } } out << "|" << endl; } out << "---------------------------------" << endl; return out; }   void Queenboard::clear_column(int col) {   if (col >= BOARDSIZE || col < 0) { throw out_of_range("Queenboard::clear_column()"); }   for (int row = 0; row < BOARDSIZE; row++) { board[row][col] = false; } }   void Queenboard::occupy_space(int row, int col) {   if (col >= BOARDSIZE || col < 0 || row >= BOARDSIZE || row < 0) { throw out_of_range("Queenboard::occupy_space()"); }   // places a queen on the board board[row][col] = true; }   bool Queenboard::is_space_under_attack(int row, int col) const {   if (col >= BOARDSIZE || col < 0 || row >= BOARDSIZE || row < 0) { throw out_of_range("Queenboard::is_space_under_attack()"); }   // check to the left int i = col - 1; while (i >= 0) { if (board[row][i]) return true; i--; }   // check diagonal up and left int j = row - 1; int k = col - 1; while (j >= 0 && k >= 0) { if (board[j][k]) return true; j--; k--; }   // check diagonal down and left j = row + 1; k = col - 1; while (j < BOARDSIZE && k >= 0) { if (board[j][k]) return true; j++; k--; }   return false; }   #endif