leetcode51&52 N-Queens

本文详细解析了N皇后问题,并提供了一种通过回溯算法来寻找所有可能的解决方案的方法。文章介绍了如何使用三个列表来记录行、左斜对角线和右斜对角线上的皇后放置情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.问题描述

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皇后问题的限制是:每一行每一列上均只能有且只有一个皇后。


二.代码编写

        典型的回溯问题,按行回溯或按列都可以。我的回溯方式是酱的,对每一列,从上到下选第一个遇到的可以填入皇后的位置填入,然后进入下一列,如果找不到可以填的位置就回溯到前一行。

        一个问题是如何判断当前位置是否可以填入,方法很简单,建3个list,分别对应行,左斜对角线,右斜对角线相应位置是否可用。

      

     因此相应位置与左对角线的对应关系是,(i , j)对应第 i+j 条左对角线。


 (i , j )对应第 n - i + j 条右对角线。


backtracking还有一个要注意的点就是回溯的停止条件,这个应该在之前用到backtracking的时候就讲到过,这里再强调一下,就是我这里的遍历方向是酱的:


所以停止条件是一直回退到了第5行,第1列。所以当行数没越界或者列数没越界时,都要继续。这就有一个问题需要再循环中处理了,就是行数越界的时候也需要backtracking。

具体代码如下:【这次代码注释hin全哦,2333】

'''
@ author: wttttt at 2016.12.04
@ problem description see: https://leetcode.com/problems/n-queens/
@ solution explanation see: http://blog.youkuaiyun.com/u014265088/article
@ github:https://github.com/wttttt-wang/leetcode
@ backtracking
'''
import copy

class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        # marigin condition
        if n == 0:
            return None
        # backtracking
        rlist = []  # all solutions, list of lists, attention to use copy.deepcopy()
        rstring = ''
        for i in range(n):
            rstring += '.'
        rlist_one = [rstring for i in range(n)]  # initialize for one solution
        row_ind = [0 for i in range(2*n-1)]  # indicates if the corresponding row is used
        left_ind = [0 for i in range(2*n-1)] # indicates if the left diagonal is used
        right_ind = [0 for i in range(2*n-1)] # indicates if the right diagonal is used
        i = 0  # indicates the row number
        j = 0  # indicates the col number
        while i < n or j > 0:  # the stop conditon of backtracking
            while i >= n:  # no available solution for this col, then backtracking
                j -= 1
                if j < 0:   # no more possible solutions
                    return rlist
                # find the Queen in previous col
                for row_i in range(n):
                    if rlist_one[row_i][j] == 'Q':
                        break
                row_ind[row_i] = 0
                left_ind[row_i+j] = 0
                right_ind[n-row_i+j-1] = 0
                rlist_one[row_i] = rlist_one[row_i][:j] + '.' + rlist_one[row_i][j+1:]
                i = row_i + 1
            # for the col j, find the likely solution with the upperest row
            flag_found = 0
            for nn in range(i, n):
                if row_ind[nn] == 1 or left_ind[nn+j] == 1 or right_ind[n-nn+j-1] == 1:
                    # this row is already used or there has been a Queen in the left/right diagonal
                    continue
                else:
                    flag_found = 1 # indicates that a targeted position is found
                    break
            if flag_found == 1:  # u have found a feasible position in col j
                rlist_one[nn] = rlist_one[nn][:j] + 'Q' + rlist_one[nn][j+1:]
                if j == n - 1:
                    # append this solution to rlist
                    rlist.append(copy.deepcopy(rlist_one))
                    rlist_one[nn] = rlist_one[nn][:j] + '.' + rlist_one[nn][j + 1:]
                    i = nn + 1  # continue finding the next solution
                else:
                    i = 0  # iterates from the first row
                    row_ind[nn] = 1  # now there is a Queen is this row
                    left_ind[nn+j] = 1
                    right_ind[n-nn+j-1] = 1
                    j += 1  # iterates to next col
            else:  # no feasible solution for this col, then backtracking
                j -= 1
                # find the Queen in previous col
                for row_i in range(n):
                    if rlist_one[row_i][j] == 'Q':
                        break
                row_ind[row_i] = 0
                left_ind[row_i+j] = 0
                right_ind[n-row_i+j-1] = 0
                rlist_one[row_i] = rlist_one[row_i][:j] + '.' + rlist_one[row_i][j+1:]
                i = row_i + 1
        return rlist
so = Solution()
n = 5
print so.solveNQueens(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值