最近在学python,自己看了点书,对照例子编程,其中讲迭代的一章提到了八皇后问题,也就是在一个国际象棋棋盘上,放8个皇后,并且皇后之间彼此不能形成威胁。小时候玩过国际象棋,知道皇后除了不能走马步其他都可以,也就是平行走或者斜走。
用list pos来表示皇后的位置,那么冲突就可以定义为以上形式。
接下去就是程序的主要部分了,每当看起算法就深深的觉得自己的智商不够用啊,网上看到一种递归方法,非常简洁,无奈自己看了好多遍感觉实在很难理解。于是自己写了个循环的,如果用for的话,感觉得8个for,肯定不靠谱,因此用while,代码如下:
真是ugly
code,不过我的水平也只能到这样了,过程还是比较好理解,先定义stepback函数用于返回上一层,并使用isback标识符确定是否返回了,如果是返回的,那就说明此层的位置不符合要求,往右移动一格,在对下一层进行操作;如果右移到了边缘,还是无解,说明无论怎么移动都没用了,那就再返回上一层。
这样以后就得到了某一个解:打印如下
# o o o o o o o
o o o o # o o o
o o o o o o o #
o o o o o # o o
o o # o o o o o
o o o o o o # o
o # o o o o o o
o o o # o o o o
使用#代表皇后的位置。要求出全部的解还得改动下代码。下面展示另一种for循环递归方法
可以看到代码非常简洁,我看了半天勉强也能理解了,这种方法不需要进退,因为迭代的for循环可以自己完成,唯一要注意的就是sol.append部分。
原本我写的就是sol.append(pos),可是结果一直不对劲,然后我直接打印pos结果又是对的,一度我都以为是我的解释器出问题了
后来才发现,这个pos的值是一直在变的,加到sol里面后,还是在改变,也就是所谓的引用传递。虽然看书的时候看到了,但自己遇到了才感觉记得深刻了,debug了半个多消失,那么我只是要简单的值传递,就用三种方法:
1、转换为tuple:tuple是不可变的,因此妥妥的是值传递了,我好像忽然明白了为什么教程里说tuple经常用作返回值
2、使用a[:]这种形式,也就是直接将list的内容交给sol,而不是将引用交付
3、deepcopy,这个就是专门用来应对这种情况的
总之以后传递list的时候要特别注意,吃一堑长壹智。最终这个递归算法可以得到92种解,其中第一种就是和我的while方法得到的一样:
就是感觉对我来说太难理解了,看懂别人的还好说,要是自己新写一个肯定想不明白