2021-06-09 蓝桥杯省赛 8皇后问题

本文详细介绍了8皇后问题的背景及两种解题方法:递归回溯与递归,并提供了具体的Python实现代码。通过实例展示了不同皇后数量下的解决方案数目。

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


8皇后问题

一、题目?

蓝桥杯省赛(中级)-第6题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

二、解题思路

1. 如何判定递归结束:

当递归到当前行==n 时,则表示前面的都已经判断好了。

1. 1 判定单元格里面可以放置皇后的方法:

1. 2 判定对应列是否可以放置皇后,如下图所示:

在这里插入图片描述

2. 代码示例

第一种方法:递归回溯

'''
_*_ coding: utf-8 _*_
@File    :   八皇后 回溯.py
@Version :   1.0
@Author  :   Solar Lee
@Time    :   2021/05/14 15:49:29
Description: Eight Queens problem solution.
'''
import time


def dfs(k):
    global nums  # 统计解法数量
    if k == n: # 当递归到第n行时说明问题已经解决。
        nums += 1  # 每当解出一种解法, 自增1.
        [print('.'*i + 'Q' + '.' * (n - i - 1)) for i in row] + [print('')] #将解法打印出来。
        return

    for i in range(n):
        if col_unused[i] and dg[i + k] and ndg[n + i - k]:
            # 保存第k列皇后的位置。
            row[k] = i
            # 将当前列的变为已探测
            col_unused[i] = dg[i + k] = ndg[n + i - k] = False
            dfs(k + 1)  # 进入下次递归
            col_unused[i] = dg[i + k] = ndg[n + i - k] = True


def main():
    dfs(0) # 从第0 行开始递归
    print(nums)

if __name__ == '__main__':
    nums = 0
    n = int(input(请输入皇后个数: ))
    dg, ndg, col_unused = [True] * (n << 1), [True] * (n << 1), [True] * n
    row = [None] * n
    start_time = time.time()
    main()
    end_time = time.time()
    print(end_time-start_time)

第二种方法:递归

"""
# -*- coding: utf-8 -*-
Created on Tue Jun  8 22:07:41 2021
@ Author: solar.lee
@ Email: solar.lee@ii-vi.com.
Description:
    To solve eight queens problem.
"""

def eight_queens(n):
    '''
    Parameters
    ----------
    n : int
        n*n array line to put n queen in it.

    Returns
    -------
    None.

    '''
    line = [0]*n # 表示初始列表,确定目前棋盘的情况。
    f(line,0,n) # 从第0行开始放皇后递归。




def f(line,m,n): # 递归函数
    '''
    Parameters
    ----------
    line : list
        current line data.
    m int:
        current line.
    n int:
        queen number.

    Returns None.

    '''
    global count
    if m == n: #递归边界这个要特别注意。
        count += 1
        print(line)
        return
    current_line = [True]*n #确认当前行的位置是否可以放置。初始化当前行状态。
    for i in range(m):
        current_line[line[i]] = False # 只要对应列有皇后,则对应列就不能放置了,即赋值为false。
        k = m - i # 只要对应列有皇后,则对应斜线就不能放置了。
        if line[i]+k<n: #右斜线
            current_line[line[i]+k] = False
        if line[i]-k>=0: # 左斜线
            current_line[line[i]-k] = False
    for i in range(n): # 遍历当前行的状态如果有True,则放入line[m],并确认对应的皇后的位置i
        if current_line[i]:
            line[m]=i
            f(line,m+1,n) # 递归往下一列。



if __name__ == "__main__":
    count = 0
    queens_quantity = int(input('请输入皇后的个数: '))
    eight_queens(queens_quantity)
    print (count)


3.输出数据:

输入:8
输出:92种
输入:7
输出:40种
输入:4
输出:2种

总结

两种方法各有特点大家多思考下看看有没有更好的方法来解决!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值