八皇后(eight queens problem)

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


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值