这类问题的求解一般是做连续猜测的的过程。若某种猜测行不通,则撤回,并用另一种猜测代替。这种反向折回并试探新步骤序列的策略称为回溯(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 seated
using 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 position
int 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;
}
}
else
cout<<"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;
else
return 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 false
static 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;
else
return 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 wrong
bool 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 board
public:
Board();
~Board();
void clear();
void display()const;
void doEightQueens();
//initiates the Eight Queens problem
int 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;
else
return false;
}
else
return 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;
else
cout<<"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;
}