递归实现八皇后问题

研究八皇后问题只是为了学习回溯,可惜还没有开始看回溯就想到了解法,也许这个解法远不如最优解,却磨灭了我学习回溯的动力。先贴上代码,以后可能会补充。

#include<iostream>
#include<vector>

#define CHESS_LOAD 1//棋子落子的时候对势力范围上的操作
#define CHESS_LEAVE -1//棋子离开的时候对势力范围上的操作

using namespace std;

//棋盘上的格子
class mapDot
{
public:
	int coverLayerNum = 0;//有多少棋子的范围覆盖在这里
};

typedef vector<vector<mapDot>> mapMat;//定义地图阵列的格式

//用于处理八皇后问题
class problemDealer
{
private:
	int mapSize = 0;//棋盘的大小 
	int chessNum = 0;//棋子的个数

	mapMat mainMap;//用于处理数据的棋盘

	int answer = 0;

	//初始化棋盘
	void mapInit();

	//将棋盘上的一个格子更改数值
	//如果能正常更改,则返回true
	bool mapDotChange(int y, int x, int fromValue);

	//一个棋子落下的时候调用的函数,fromvalue表示的是落下还是离开
	//函数的过程需要在棋子的势力范围上修改势力参数
	void chessLoadFunc(int y, int x, int fromValue);

	//各种情况枚举的递归操作
	//含义上表示剩余几个棋子的时候有多少种放法
	int loadChessSitNum(int chessLess);
public:
	//fromMapSize表示地图的大小,另一个表示棋子的个数
	problemDealer(int fromMapSize,int fromChessNum);

	//开始计算
	void beginCaclute();

	//输出答案的计算结果
	void printAns();
};

//初始化棋盘
void problemDealer::mapInit()
{
	for (int y = 0; y < mapSize; ++y)
	{
		//新建一行
		mainMap.push_back(vector<mapDot>());
		for (int x = 0; x < mapSize; ++x)
		{
			mainMap[y].push_back(mapDot());
		}
	}
}

//将棋盘上的一个格子更改数值
//如果能正常更改,则返回true
bool problemDealer::mapDotChange(int y, int x, int fromValue)
{
	//判断是否为合法的坐标
	if (y < 0)
		return false;
	if (x < 0)
		return false;
	if (y >= mapSize)
		return false;
	if (x >= mapSize)
		return false;

	//更改数值
	mainMap[y][x].coverLayerNum += fromValue;
	return true;
}

//一个棋子落下的时候调用的函数,fromvalue表示的是落下还是离开
//函数的过程需要在棋子的势力范围上修改势力参数
void problemDealer::chessLoadFunc(int y, int x, int fromValue)
{
	//纵方向
	for (int i = 1;; ++i)
	{
		//判断是否为合法数值,并更改
		if (!mapDotChange(y - i, x, fromValue))
			break;
	}

	//左斜方向
	for (int i = 1;; ++i)
	{
		if (!mapDotChange(y - i, x - i, fromValue))
			break;
	}

	//右斜方向
	for (int i = 1;; ++i)
	{
		if (!mapDotChange(y - i, x + i, fromValue))
			break;
	}
}

//各种情况枚举的递归操作
//含义上表示剩余几个棋子的时候有多少种放法
int problemDealer::loadChessSitNum(int chessLess)
{
	//判断递归的返回条件
	if (!chessLess)//说明所有的棋子都已经放完
		return 1;

	int possSitNum = 0;//可能的情况的个数
	//根据当前棋子的对应行找这一行上可以落子的地方
	for (int x = 0; x < mapSize; ++x)
	{
		//判断当前位置是否可落子
		if (mainMap[chessLess - 1][x].coverLayerNum == 0)
		{
			//在当前位置落子
			chessLoadFunc(chessLess - 1, x, CHESS_LOAD);
			//计数可能的情况
			possSitNum += loadChessSitNum(chessLess - 1);
			//将棋子取下时候的操作
			chessLoadFunc(chessLess - 1, x, CHESS_LEAVE);
		}
	}
	return possSitNum;
}


//fromMapSize表示地图的大小,另一个表示棋子的个数
problemDealer::problemDealer(int fromMapSize, int fromChessNum)
{
	mapSize = fromMapSize;
	chessNum = fromChessNum;
}

//开始计算
void problemDealer::beginCaclute()
{
	//初始化棋盘
	mapInit();

	//判断问题是否可解
	if (chessNum <= mapSize)
	{
		//保存计算结果
		answer = loadChessSitNum(chessNum);
	}
}

//输出答案的计算结果
void problemDealer::printAns()
{
	cout << answer << endl;
}


int main()
{
	problemDealer tempDealer(8, 8);
	tempDealer.beginCaclute();
	tempDealer.printAns();

    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值