7-2 N 皇后问题
分数 30
全屏浏览
切换布局
作者 usx程序设计类课程组
单位 绍兴文理学院
要求在n*
n格的棋盘上放置彼此不会相互攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
输入格式:
测试数据有多组,处理到文件尾。对于每组测试,输入棋盘的大小n(1<n<12)。
输出格式:
对于每组测试,输出满足要求的方案个数。
输入样例:
4
输出样例:
2
代码长度限制
16 KB
Python (python3)
时间限制
4000 ms
内存限制
64 MB
其他编译器
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
解题思路:
一、问题分析:
1.N个皇后需要放在N×N的棋盘上
2.皇后不能在同一行、同一列或同一斜线上
3.需要计算所有可能的解法数量
二、使用回溯法的原因:
1.需要尝试所有可能的放置方式
2.当发现冲突时可以及时回退
3.适合解决排列组合类问题
三、 核心函数说明:
# 检查位置是否安全
def is_safe(board, row, col, n):
# 检查三个方向:
# 1. 同列
# 2. 左上对角线
# 3. 右上对角线
# 回溯函数
def backtrack(board, row):
# 基本情况:到达最后一行
# 递归情况:尝试在当前行的每一列放置皇后
四、算法步骤:
1.从第一行开始,逐行放置皇后
2.对每一行,尝试在每一列放置皇后
3.检查放置位置是否安全
4.如果安全,继续处理下一行
5.如果不安全或需要回溯,移除皇后并尝试下一个位置
时间复杂度:
- O(N!),其中N是棋盘大小
- 实际运行时间会因为剪枝而小于这个上限
空间复杂度:
- O(N²),需要N×N的棋盘数组
完整代码展示
def is_safe(board, row, col, n):
# 检查同一列
for i in range(row):
if board[i][col] == 1:
return False
# 检查左上对角线
for i, j in zip(range(row-1, -1, -1), range(col-1, -1, -1)):
if board[i][j] == 1:
return False
# 检查右上对角线
for i, j in zip(range(row-1, -1, -1), range(col+1, n)):
if board[i][j] == 1:
return False
return True
def solve_n_queens(n):
def backtrack(board, row):
# 如果已经放置了n个皇后,找到一个解
if row == n:
return 1
count = 0
# 尝试在当前行的每一列放置皇后
for col in range(n):
if is_safe(board, row, col, n):
# 放置皇后
board[row][col] = 1
# 继续处理下一行
count += backtrack(board, row + 1)
# 回溯,移除皇后
board[row][col] = 0
return count
# 创建n*n的棋盘
board = [[0 for _ in range(n)] for _ in range(n)]
return backtrack(board, 0)
def main():
try:
while True:
n = int(input())
if n < 1 or n > 11: # 根据题目限制 1<n<12
break
result = solve_n_queens(n)
print(result)
except EOFError:
pass
if __name__ == "__main__":
main()
运行截图