不引入标准库和第三方库,不用分号将多行代码写在一行,再10行代码之类求出八皇后问题的所有解。
---------------------------------------------------------------------------------------
输出结果为列表l,l[i]表示第i+1行的皇后应放置的列序号。l的初始值是[0]*8,如果第1行的皇后放置在第一列,那么输出值中l[0]=1。
思路图:
l[0] l[1] l[2] l[3] l[4] l[5] l[6] l[7]
i |
k |
m |
从第1行开始一次放置皇后,
指针i用于标定现在正在放置哪一行的皇后,当放置完成后,指针i向后移动一位(如放置完第6行,指针i从l[5]移动到l[6],并开始放置第7行的皇后)。
指针k用于检验第i+1行的皇后是否与第k+1行的皇后在同一列或同一条直线上。如果不满足条件,将i指针所指的元素加1(将第i+1行的皇后向右移动一列),k指针归0(重新检验)。
指针m用于检验各元素是否溢出,因为棋盘只有8列,所以各元素的值只能取1到8,如果前i行的皇后放置得不好,可能造成在第i+1行,不论把皇后放在哪一列,都不能满足条件。这种情况下,按照对指针k和指针i的定义,元素l[i]的值会超过8。因此,当最终确定l[i]的值后,指针m从l[i]开始,检验元素是否大于8,如果没有,m向前移以为(这个操作貌似不必要,以后看看可不可以在不增加代码行数的情况下省略);如果有,将该元素归零后,m向前移动一位,给将前一位元素加一(即方向第i+1行放不了皇后,把第i行皇后向右移动一列,再看看能不能放得下),然后继续检查这个元素是否大于8(如果第i行的元素本身就在第8行了,那么只能再把这一行的皇后重新放置,并把第i-1行的皇后右移一位)。当指针m移到某个元素,给该元素加1后,检测到该元素没有大于8,将指针i移动至这个位置,继续进行前面两个步骤。
输出八皇后问题第一个解的代码:
l, i = [0]*8, 0
while i < 8:
k, l[i] = 0, l[i] + 1
while k < i:
if l[i] == l[k] or abs(l[i] - l[k]) == i - k: l[i], k = l[i] + 1, -1
k += 1
i += 1
for m in range(i - 1, 0, -1):
if l[m] > 8: l[m], i = 0, m - 1
print(l)
输出八皇后问题所有解的代码:
l, i = [0]*8, 0
while l[0] < 9:
k, l[i] = 0, l[i] + 1
while k < i:
if l[i] == l[k] or abs(l[i] - l[k]) == i - k: l[i], k = l[i] + 1, -1
k += 1
for m in range(i, 0, -1):
if l[m] > 8: l[m], i = 0, m - 2
if i < 7: i += 1
else: print(l)
这两个代码的区别在于:
对于第一个脚本,当确定第8行皇后的位置后(确定l[7]的值后),将指针i移出列表索引的范围,因此不满足第2行的判定条件,循环结束。然后输出列表l
l[0] l[1] l[2] l[3] l[4] l[5] l[6] l[7]
i |
k |
m |
对于第二个脚本,当确定第8行皇后的位置后(确定l[7]的值后),输出列表值(触发第10行else条件),将指针i不动。继续循环,按要求继续移动3个指针。注意到按照我所给定的条件移动指针和更新数值,当找完8皇后问题的所有解后,l[0]必将溢出正常范围,因此,我们将循环结束的条件设置为l[0]>=9。