八皇后问题,国际象棋盘上放8个皇后,互相不能攻击。这个问题如此有名,很多不会下国际象棋的人都听说过。
所有可能的布局解一共有92种,但其中大部分是重复的,比如左右对称,或者是旋转棋盘对称。据说其中完全独立的布局一共只有12种。虽然我得到了一个12个不同的布局,但在网上一直没有找到12种布局图,所以无法验证。
92种解
用python求解92种布局是比较简单的,网上算法有很多(不知道去重之后有多少种),这里展示一个自己原创的解法。算法的特点是使用了字典来记录局面,使用yield机制来返回结果。这样的算法应该是具有足够多的python特色了。
def checkBoard(A, col, row):
flag= True
for i in range(col):
if A[i] == row or abs(row - A[i]) == col - i:
flag = False
break
return flag
def queen(size, col=0, A={}):
for row in range(size):
if checkBoard(A, col, row):
A[col]=row
if col==size-1:
yield [row]
else:
ret= queen(size, col+1, A)
for item in ret:
yield [row]+item
ret= queen2(8)
上面这两个算法,在全部12种解法种,是唯二的具有角落点的布局。人工对比可以保证不重复。
12种不同解
去重算法,相对比较暴力。一个布局,它的衍生布局一共有8个:
- 自身
- 左右翻转
- 上下翻转
- 左右上下翻转
- 自身行列互换
- 左右翻转行列互换
- 上下翻转行列互换
- 左右上下翻转行列互换
逐个检视92个布局,选择完全不同的布局加入另外一个列表,最后获得12布局解。
def rot(A):
B= [-1]*8
for i in A:
B[A[i]]=i
return B
def sameBoard(A, B):
B2= B[::-1]
B3= [7-x for x in B]
B4= rot(B)
B5= rot(B2)
B6= rot(B3)
B7= [7-x for x in B2]
B8= rot(B7)
B_like=[B2,B3,B4,B5,B6,B7,B8]
if A in B_like:
return 1
return 0
上面这七个布局,至少有一个点在某条边的第二点上。
画图
这里是画棋盘和棋子布局的代码。
def drawBoard(board, num):
from PIL import Image
a= 55
b= 55
xd= 43
yd= 43
back= Image.open('棋盘.png')
back= back.convert('RGB')
qun= Image.open('queen_trans.png')
qun= qun.resize((a,b), Image.ANTIALIAS)
_,_,_,af= qun.split()
for i in board:
x= i*a+ xd
y= board[i]*b+ yd
back.paste(qun, (x,y), af)
back.save('%d.jpg'%num)
最后这三个布局,不存在角落点与第二点。