我必须为N-queen棋盘问题编写代码。我理解它背后的理论,但不明白我应该如何编码它。在本练习中,0代表空格,而1代表皇后)
到目前为止,我只写了:1 require 'test_helper'
2 class UnitTemplatesControllerTest < ActionController::TestCase
在此之后,我想定义这个板中的行是什么以及该板中的列是什么。所以我能够定义棋盘上的女王之间的碰撞。
谢谢。
答案 0 :(得分:1)
我不知道我应该多少帮助你(听起来像是一个家庭作业),但我的好奇心被激怒了。所以这是一个初步的探索:
将电路板表示为0/1的8x8阵列非常简单:
In [1783]: B=np.zeros((8,8),int)
但是,由于解决方案每行需要1个大写,每列只需要1个,我可以将其表示为列数的排列。在线查找我找到了一个解决方案,我可以输入:
In [1784]: sol1=[2,5,1,6,0,3,7,4]
我可以将它映射到电路板上:
In [1785]: B[np.arange(8),sol1]=1
In [1786]: B # easy display
Out[1786]:
array([[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 1, 0, 0, 0]])
测试这个怎么样?使用numpy
可以轻松地对行和列求和。对于有效的解决方案,这些必须全部为1:
In [1787]: B.sum(axis=0)
Out[1787]: array([1, 1, 1, 1, 1, 1, 1, 1])
In [1788]: B.sum(axis=1)
Out[1788]: array([1, 1, 1, 1, 1, 1, 1, 1])
对角线的长度不同,但也可以相加
In [1789]: np.diag(B,0)
Out[1789]: array([0, 0, 0, 0, 0, 0, 0, 0])
并查看其他对角线,'翻转'栏:
In [1790]: np.diag(B[:,::-1],1)
Out[1790]: array([0, 1, 0, 0, 0, 0, 0])
我可以使用列表理解生成所有对角线(不一定是最快的方式,但很容易测试):
In [1791]: [np.diag(B,i) for i in range(-7,8)]
Out[1791]:
[array([0]),
array([0, 0]),
array([0, 0, 0]),
array([1, 0, 0, 0]),
array([0, 0, 0, 0, 1]),
array([0, 0, 0, 1, 0, 0]),
array([0, 1, 0, 0, 0, 0, 0]),
array([0, 0, 0, 0, 0, 0, 0, 0]),
array([0, 0, 0, 0, 0, 0, 1]),
array([1, 0, 0, 0, 0, 0]),
array([0, 0, 0, 1, 0]),
array([0, 1, 0, 0]),
array([0, 0, 0]),
array([0, 0]),
array([0])]
和另一个方向,总和:
In [1792]: [np.diag(B[:,::-1],i).sum() for i in range(-7,8)]
Out[1792]: [0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0]
没有对角线可以有一个&gt; 1,但有些可能是0。
如果建议的解决方案确实是np.arange(8)
的置换,则保证满足行和列求和测试。这只是离开对角线测试。电路板映射可能很适合显示目的,但不需要表示解决方案。它可能不是测试对角线的最佳方法。
蛮力解决方案是生成所有排列,并测试每个排列。
In [1796]: len(list(itertools.permutations(range(8))))
Out[1796]: 40320
当然,有更智能的方法来生成和测试解决方案。
几个月前,我参与了数独谜题问题
Why is translated Sudoku solver slower than original?
最初的问题是列表或数组是否是更好的表示。但我发现,在AI网站上,一个高效,智能的求解器可以用字典书写。
有很多SO问题标记为Python并涉及8个皇后。也很少用numpy
标记。
==========
您的初始设置:
board[0:,0]=1
将通过行总和测试,未通过列总和测试,并通过对角线测试。