研究了一下午的八皇后算法,可算是搞明白了,为了避免以后忘记,还是写个博客吧!可能会跟其他文章有相似之处,最终还是希望能好好学习算法,都是经过自己思考后亲自写的代码,虽然过程比较艰难,我写了很多注释。
参考B站视频链接 :2021第十二届蓝桥杯青少组省赛Python第6题(八皇后问题)_哔哩哔哩_bilibili
目录
一、问题描述
二、解题思路
三、总体步骤
四、代码实现
寻找函数编写:
打印输出函数:
主调用函数:
测试结果:
个人心得
一、问题描述
有八个皇后,如何在8*8的棋盘上放置8个皇后,使得任意两个皇后都不在同一条横线、纵线或斜线上
二、解题思路
三、总体步骤
四、代码实现
寻找函数编写:
# row表示递归到第几行,初始从第0行开始,n表示棋盘规模n行n列,这个始终不变
def search(row, n):global count # 声明全局变量for col in range(n):# 表示在同一条上对角线上:行号加列号相同;表示在同一条下对角线上:行号减列号相同,为了避免索引出现复数,用row-col+n-1if 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 # 占领后将该点所在 的列 标记为1line_up[row+col] = 1 # 该点所在的 上对角线 被标记为1line_do[row-col+n-1] = 1 # 该点所在的 下对角线 也标记为1if row < n-1:# 如果该行不是棋盘的最后一行,则继续递归调用,寻找下一行的占领点,行数row+1search(row+1, n)else:# 已经到了最后一行,则证明找到一组可行的八皇后摆放点count += 1printf(place, n) # 将这个解的形状打印输出print(place) # 输出该结果# 到这里已经找到一个解,在寻找下一个解之前,要将棋盘的标记清空flag_y[col] = 0line_up[row + col] = 0line_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 # 存储可行解的个数# 表示标记,初始标记都为0place = [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++的代码也要看得懂,毕竟很多经典算法都是用这些编写的,算法核心思想都是一样的,参加比赛选一个自己喜欢的编程语言就好。