LeetCode51.N皇后问题

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
在这里插入图片描述

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例:
输入:4
输出:[
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],

["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。

分析:若在棋盘上已放置一个皇后,以这个皇后为中心,上、下、左、右、左上、左下、右上、右下8个方向的位置全被占据。
在这里插入图片描述
回溯算法:N皇后问题,对于N*N棋盘,每行都要放置1个且只能放置1个皇后。利用递归对棋盘的每一行放置皇后,放置时,按列顺序寻找可以放置皇后的列,若可以放置皇后,将皇后放置到位置,并更新mark标记数组,递归进行下一行的皇后放置;当该次递归结束后,恢复mark标记数组,并尝试下一个可能放皇后的列。
当递归可以完成N行的N个皇后放置,则将该结果保存并返回。
在这里插入图片描述

class Solution{
	vector<vector<string>> solveNQueens(int n) {
		vector<vector<int>> mark;
		vector<vector<string>> result;
		vector<string> temp;	//存放某次结果,当完成一次递归成功找到结果后将temp放入result中
		//初始化标记数组和临时结果
		for(int i = 0; i < n; i++) {
			mark.push_back(vector<int>());
			for(int j = 0; j < n; j++) {
				mark[i].push_back(0);
			}
			temp.push_back("");
			temp[i].append(n,'.');
		}
		generate(0,n,temp,result,mark);
		return result;
	}
	
	void push_queen(int x,int y,vector<vector<int> > &mark) {
		//两个方向数组
		static const int dx[] = {-1,1,0,0,-1,-1,1,1};
		static const int dy[] = {0,0,-1,1,-1,1,-1,1};
		mark[x][y] = 1;
		//以x,y为中心,按照八个方向向外延申N个距离,只要不超过边界,就将这个位置标记为已经被占据
		for(int i = 1; i < mark.size(); i++) {
			for(int j = 0; j < 8; j++) {
				int new_x = x + dx[j] * i;
				int new_y = y + dy[j] * i;
				if(new_x >=0 && new_x < mark.size() && new_y >= 0 && new_y < mark.size()) {
					mark[new_x][new_y] = 1;
				}
			}
		}
	}
	
	void generate(int k,int n,vector<string> &temp,vector<vector<string> > &result,vector<vector<int> > &mark) {
		if(k == n) {	//这次递归完成了N皇后的放置
			result.push_back(temp);
			return;			
		}
		for(int i = 0; i < n; i++) {	//按顺序每列尝试放置皇后
			if(mark[k][i] == 0) {	//这一列可以放置皇后
				vector<vector<int>> tmp_mark = mark;	//临时的标记数组
				temp[k][i] = 'Q';	//记录当前皇后的位置
				push_queen(k,i,mark);	//更新能放皇后的位置
				generate(k+1,n,temp,result,mark);	//递归下一行
				mark = tmp_mark;	//下一行不能放,回溯到当前行,继续往下一列放置	
				temp[k][i] = '.';	//当前尝试放皇后的位置重新置为'.'
			}
		}
	}
};

int main(void) {
	vector<vector<string> > result;
	Solution s;
	result = s.solveNQueens(4);
	for(int i = 0; i < result.size(); i++) {
		for(int j = 0; j < result[i].size(); j++) {
			cout<<result[i][j]<<endl; 
		}
		cout<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值