研究了一下午的八皇后算法,可算是搞明白了,为了避免以后忘记,还是写个博客吧!可能会跟其他文章有相似之处,最终还是希望能好好学习算法,都是经过自己思考后亲自写的代码,虽然过程比较艰难,我写了很多注释。
目录
一、问题描述
二、解题思路
三、总体步骤
四、代码实现
寻找函数编写:
打印输出函数:
主调用函数:
测试结果:
个人心得
一、问题描述
有八个皇后,如何在8*8的棋盘上放置8个皇后,使得任意两个皇后都不在同一条横线、纵线或斜线上
二、解题思路
三、总体步骤
四、代码实现
寻找函数编写:
# row表示递归到第几行,初始从第0行开始,n表示棋盘规模n行n列,这个始终不变
def search(row, n):
global count # 声明全局变量
for col in range(n):
# 表示在同一条上对角线上:行号加列号相同;表示在同一条下对角线上:行号减列号相同,为了避免索引出现复数,用row-col+n-1
if flag_y[col] == 0 and line_up[row+col] == 0 and line_do[row-col+n-1] == 0:
# 如果该点所在的行、列、对角线都没有被标记,则该点可以占领
place[row] = col # 表示第row行的第col列被占领:例如place[0] = 1 表示第1行的第2个点被占领
flag_y[col] = 1 # 占领后将该点所在 的列 标记为1
line_up[row+col] = 1 # 该点所在的 上对角线 被标记为1
line_do[row-col+n-1] = 1 # 该点所在的 下对角线 也标记为1
if row < n-1:
# 如果该行不是棋盘的最后一行,则继续递归调用,寻找下一行的占领点,行数row+1
search(row+1, n)
else:
# 已经到了最后一行,则证明找到一组可行的八皇后摆放点
count += 1
printf(place, n) # 将这个解的形状打印输出
print(place) # 输出该结果
# 到这里已经找到一个解,在寻找下一个解之前,要将棋盘的标记清空
flag_y[col] = 0
line_up[row + col] = 0
line_do[row-col+n-1] = 0
打印输出函数:
# 输出棋盘样式
def printf(pos, n):
# 遍历n*n的棋盘格子
for i in range(n):
for j in range(n):
if pos[i] == j:
# 如果第i行的皇后放在了第j列上,就输出*表示皇后的位置
print("*", end=" ")
else:
print('0', end=" ")
print()
主调用函数:
if __name__ == '__main__':
n = int(input("请输入棋盘的规模n\n")) # 代表n*n棋盘
count = 0 # 存储可行解的个数
# 表示标记,初始标记都为0
place = [0 for i in range(n)] # 记录第几行的皇后放在第几列上
flag_y = [0 for i in range(n)] # 表示第i列是否被标记(占领)
line_up = [0 for i in range(2 * n - 1)] # 上对角线是否被标记,总共有2n-1条上对角线
line_do = [0 for i in range(2 * n - 1)] # 表示下对角线是否被标记,总共有2n-1条下对角线
search(0, n) # 从第0行开始寻找
print("总共有{}种结果".format(count))
测试结果:
测试结果是正确的,如果是4*4的棋盘,总共有两个解;如果是8*8的棋盘,总共有92个解。
个人心得
理解算法一定不能急,每一步都要搞懂,网上关于这个题有很多种算法,我觉得只要抓住一种吃透就好。还有最近也看了很多博主对算法学习的看法,感觉自己收获了很多,最大的感触就是:语言并不是学习算法的障碍,用python写并不比用C、C++的人差,语言只是一个工具罢了,我们应该慢慢打破语言之间的壁垒,所以首先C、C++的代码也要看得懂,毕竟很多经典算法都是用这些编写的,算法核心思想都是一样的,参加比赛选一个自己喜欢的编程语言就好。