leetcode 刷题之路 94 N-Queens

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

For example,
There exist two distinct solutions to the 4-queens puzzle:

[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]

非常经典的N皇后问题:在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一对角线上的皇后都会自动攻击)。

采用回溯来解决这个问题。

回溯法解决的问题都可以用枚举法解决,对于E中的任意一个元祖,逐个检查其是否满足约束集D,如果满足,就为问题的一个解,枚举法的缺点在于计算量大,而回溯法在搜索过程中,一旦发现原先的选择并不优或者达不到目标,立即回溯到前一步重新选择,简单的说,回溯法的思想就是-此路不通,掉头重新选路,这样能够避免无效搜索,降低了算法复杂度。

回溯法解决问题的一般思路为:

(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

N皇后的问题可以这样求解,从上至下依次在每一行放置皇后,进行搜索,若在某一行的任意一列放置皇后均不能满足要求,则不再向下搜索,而进行回溯,回溯至有其他列可放置皇后的一行,再向下搜索,直到搜索至最后一行,找到可行解,输出。

Accepted Solution:

class Solution {
 public:
	 vector<vector<string> > solveNQueens(int n)
	 {
		 vector<vector<string>> res;
		 vector<string> board(n, string(n, '.'));
			 helper(res, board, 0, n);
		return res;
	 }
	 void helper(vector<vector<string>> &res, vector<string> &board, int row, int n)
	 {
		 if (row == n)
			 res.push_back(board);
		 for (int clmn = 0; clmn<n; clmn++)
		 {
			 if (isValid(board, row, clmn,n))
			 {
				 board[row][clmn] = 'Q';
				 helper(res, board, row + 1, n);
				 board[row][clmn] = '.';
			 }
		 }
	 }
	 bool isValid(vector<string> &board, int row, int clmn, int n)
	 {
		 for (int i = 0; i<n; i++)
		 if (board[i][clmn] == 'Q')
			 return false;
		 for (int i = 0; i<n; i++)
		 if ((i + row - clmn) >= 0 && (i + row - clmn) < n && board[i + row - clmn][i] == 'Q')
			 return false;
		 for (int i = 0; i<n; i++)
		 if ((i + row + clmn - n + 1) >= 0 && (i + row + clmn - n + 1) < n && board[i + row + clmn - n + 1][n-1-i] == 'Q')
			 return false;
		 return true;
	 }
 };



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值