八皇后(eight queens problem)

来源:互联网 发布:创维e780u安装软件 编辑:程序博客网 时间:2024/04/29 15:50

这类问题的求解一般是做连续猜测的的过程。若某种猜测行不通,则撤回,并用另一种猜测代替。这种反向折回并试探新步骤序列的策略称为回溯(backtracking)。

八皇后规则的描绘大家应都已熟悉了,这里我就不多说。八皇后问题的解决要用到递归和回溯的方法。下面是我基于数组的尝试:

#include<iostream>#include<cmath>#include<cstdlib>//here using the array arr's index as the col of the queen  seated//and using the array arr's values as the row of the queen seatedusing namespace std;bool placeQueen(int *arr,int row,int size);bool safe(int *arr,int row)// decide whether the queen that will be set is safe in current positionint main(){        const int MAX=16;int arr[MAX]={0,0,0,0,0,0,0,0};cout<<"PlaceQueen :"<<endl;int first=0;char table[MAX][MAX];// simulating board;           bool success =placeQueen(arr,first,MAX);  if(success){cout<<"place eight queens success !"<<endl;                //put the queens on the simulation board;                for(int i=0;i<MAX;i++){for(int j=0;j<MAX;j++){table[j][i]='O';}                        table[arr[i]][i]='*';cout<<i+1<<" ";      }cout<<endl;                // display the status that queens how was seted on board;for(int i=0;i<MAX;i++){for(int j=0;j<MAX;j++)       cout<<table[i][j]<<" ";cout<<i+1<<endl;}}elsecout<<"place eight queens failed !"<<endl;return 0;}bool safe(int *arr,int row){if(row==0)return true;else{        int i=0;        while((i<row)&&(arr[row]!=arr[i])&&(abs(arr[row]-arr[i])!=abs(row-i)))                {i++;}if(i==row)return true;elsereturn false;                   }}bool placeQueen(int *arr,int row,int size){if(row>size-1)return true;else{bool isok=false;while(!isok&&arr[row]<size){if(safe(arr,row))         isok=placeQueen(arr,row+1,size);if(!isok){        arr[row+1]=0;arr[row]++;}}return isok;}}

基于vector的尝试:

这里要用到queen类,其中定义了queen目前所在的位置信息(col and row ),判断是否会受到攻击的函数。另外一个static const 常量用于将queens 限定在一个board上面:

#ifndef QUEEN_H_#define QUEEN_H_#include"board.h"class Board;class Queen{private:int row;int col;static const Board *boardPtr;public:Queen();Queen(int _row,int _col);int getRow()const;int getCol()const;void nextRow();bool isUnderAttack()const;//Detemines whether the queen is under attack by another//queen .if there is a queen same row or the same diagonal //return true;otherwise return falsestatic void setBoard(const Board *bPtr);//save a pointer to the board for all queens};#endif
#include"queen.h"#include<cmath>#include<cstddef>const Board *Queen::boardPtr=NULL;void Queen::setBoard(const Board *bPtr){      boardPtr=bPtr;}Queen::Queen(){row=col=0;}Queen::Queen(int _row,int _col):row(_row),col(_col){}int Queen::getRow()const{return row;}int Queen::getCol()const{return col;}void Queen::nextRow(){row++;}bool Queen::isUnderAttack()const{int i=0;while((i<col)&&(boardPtr->getQueen(i)->getRow()!=row)&&(std::abs(boardPtr->getQueen(i)->getCol()-col)!=std::abs(boardPtr->getQueen(i)->getRow()-row))){i++;}if(i==col)return false;elsereturn true;}

board也用一个类来定义,其实现用的是标准库vector类,vector 的不同索引中存放了不同位置的queen;其主要操作是,尝试一个安全的位置,并放置queen于其上。


#ifndef BOARD_H_#define BOARD_H_#include<vector>#include<cassert>#include<cstddef>#include<iostream>#include"queen.h"class Queen;using namespace std;static const int BOARD_SIZE=8;class Board{private:vector<const Queen*> queens;//maybe something wrongbool isQueen(int _row,int _col)const;//determines wherther there is a queen in //position(int _row,int _col)bool placeQueens(Queen *queenPtr);//Attempts to place queens on board starting//with designated queen.void removeQueen();//remove the last queen on the board, but does not delete//it.void setQueen(const Queen *queenPtr);//Place a queen on the boardpublic:Board();~Board();void clear();void display()const;void doEightQueens();//initiates the Eight Queens problemint getNumQueens()const;const Queen * getQueen(int index)const;//return a pointer to the queen at the designated index};#endif
#include"board.h"Board::Board(){queens=vector<const Queen*>();}Board::~Board(){clear();}bool Board::isQueen(int _row,int _col)const{if(_row<queens.size()){if(queens[_row]->getCol()==_col)return true;elsereturn false;}elsereturn false;}bool Board::placeQueens(Queen *queenPtr){if(queenPtr->getCol()>=BOARD_SIZE){delete queenPtr;return true;}else{bool success =false;while((!success)&&(queenPtr->getRow()<BOARD_SIZE)){      if(queenPtr->isUnderAttack()){queenPtr->nextRow();}else{setQueen(queenPtr);Queen *newQueenPtr=new Queen(0,queenPtr->getCol()+1);assert(newQueenPtr!=NULL);success=placeQueens(newQueenPtr);if(!success){delete newQueenPtr;removeQueen();queenPtr->nextRow();}}}return success;}}void Board::removeQueen(){queens.pop_back();}void Board::setQueen(const Queen *queenPtr){queens.push_back(queenPtr);}void Board::clear(){int num=getNumQueens();for(int i=num-1;i>=0;i--){delete queens[i];removeQueen();}}void Board::doEightQueens(){Queen *qPtr=new Queen(0,0);assert(qPtr!=NULL);bool isok=placeQueens(qPtr);if(isok)cout<<"do eight queens success !"<<endl;elsecout<<"do eight queens failed !"<<endl;}int Board::getNumQueens()const{return queens.size();}void Board::display()const{for(int i=0;i<getNumQueens();i++){cout<<queens[i]->getCol()<<"  "<<queens[i]->getRow()<<endl;}}const Queen * Board::getQueen(int index)const{return queens[index];}

下面是主函数,用来测试一下

#include"queen.h"#include"board.h"int main(){Board aboard;Queen::setBoard(&aboard);cout<<"lalal";aboard.doEightQueens();        aboard.display();return 0;}