Leetcode算法——51~52、n皇后问题

76 篇文章 1 订阅

n皇后问题需要将n个皇后放置在n*n的棋盘上,保证任意两个皇后都不能处于同一行、同一列或同一斜线上。

51、给定一个整数n,返回n皇后问题的所有不重复的解。
51、给定一个整数n,返回n皇后问题的所有不重复的解的个数。

每个解都是一种n个皇后的布局,其中 ‘Q’ 和 ‘.’ 分别代表皇后和空白。

示例:

Input: 4
Output: [
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

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

思路

n皇后问题是典型的回溯法教材。

所谓回溯法,是在递归的基础上,增加了回溯(即反悔的操作),先假设我采用方法A解决当前问题,然后继续递归剩下的任务,最后回过头来进行反悔,不这样做了,而改用方法B来解决这个问题,然后继续递归。

使用回溯法,能够实现对所有满足要求情况的枚举,同时最大程度减少不满足要求的枚举(因为一旦中间某个过程不满足要求,则剩下的过程不再继续递归)

以n皇后为例,可以这样做:

  • 初始化一个n*n的空棋盘
  • 尝试在第1行第1列中安放一个皇后,判断放在这里之后整个棋盘是否尚且满足要求,如果满足,则继续递归第2行;如果不满足,则回溯:将皇后从第1行第1列删掉,改为放在第1行第2列。
  • 继续判断放在第1行第2列之后整个棋盘是否满足要求,以此类推。
  • 递归结束:一旦最后一行中某一列安放一个皇后,可以使得整个棋盘满足要求,那么便求出了一个解。
  • 我们要求寻找到所有不重复的解,因此这时算法还不能结束,继续回溯:倒数第2行的皇后向右移动一格,继续递归。
  • 直至所有循环都退出。

python实现

def solveNQueens(n):
    """
    :type n: int
    :rtype: List[List[str]]
    回溯法。
    """
    
    def place_queen(result_list, place_list, cur_row):
        '''
        在第 cur_row 行上放置一个皇后。
        result_list:存放所有的解
        place_list:长度为n,每一个元素代表这一行上的皇后的位置
        '''
        
        # 递归结束条件
        if cur_row == len(place_list):
            # 将答案转为二维棋盘,放入到result_list中
            # 如果是返回解的个数,则不需要转为二维棋盘,直接统计result的个数即可
            result_list.append(['.'*i + 'Q' + '.'*(n-i-1) for i in place_list])
            return
        
        # 在cur_row这一行上对所有位置依次尝试放置皇后
        for cur_col in range(n):
            place_list[cur_row] = cur_col
            
            # 判断是否有同行同列同斜边的皇后
            for row in range(cur_row):
                col = place_list[row]
                if col == cur_col or abs(cur_col - col) == cur_row - row:
                    break
            else:
                # 没有break,说明有效,继续放置下一行
                place_queen(result_list, place_list, cur_row + 1)
    
    result_list = []
    place_queen(result_list, [0] * n, 0)
    return result_list

def output_board(board_list):
    '''
    输出棋盘
    '''
    print(f'共{len(board_list)}种解法')
    for board in board_list:
        print(' ')
        for row in board:
            print(row)

if '__main__' == __name__:
    n = 4
    output_board(solveNQueens(n))
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值