N皇后区,X由Y董事会决定问题面试问题


10

今天在一次采访中有人问我以下问题,从那以后我一直在思考。我无法回答,也无法在线找到解决方案。

给定一个棋盘尺寸为X乘以Y和N个皇后的棋盘,请确定是否有可能将这些皇后安排在棋盘上,以使它们不会互相攻击。

具有2个皇后的2 x 3电路板确实有解决方案,因此算法将返回true:

Q . .
. . Q

我正在寻找一种解决这个难题的编程方法,例如,不仅仅是纸上解决难题的方法。


当然,“ 最佳优先搜索”也是一个选择,其他搜索启发式也是一样
Jason

2
提名有史以来最糟糕的采访问题之一-除非软件,他们就依靠回溯解决方案的工作,在这种情况下,它是完全相关
史蒂芬答洛韦

1
公平地说,面试官说这只是一种额外的荣誉。其余的采访是相当合法的海事组织。我只是好奇而已。
受访者

也许这是一个测试,他是否会使用Caleb在其回答中陈述的事实进行回溯或(考虑寻找)O(1)解决方案进行模拟。编写简单事物的能力并不是工作中需要的一切。
Sopel

作业显然不在这里讨论。
jwenting

Answers:


16

从编程的角度来看,这不是(IMO)一个非常有趣的问题。您可以想出一种递归算法来尝试各种排列,如下所示:

bool try_queens(Board board, int n)
{
    if (n == 0) {
        // no queens left to place, so we're done
        return true
    }
    // try each open position until we find one that works
    for each position on the board {
        if (is_empty(board, position) and not is_attacked(board, position)) {
            place_queen(board, position)
            if (try_queens(board, n-1)) {
                return true
            }
            remove_queen(board, position)
        }
    }
    // if we get this far, there's no available position
    return false
}

main()
{
    initialize board(X,Y)
    return try_queens(board, N)
}

如果您稍微考虑一下问题,您会意识到无法将N个皇后装在X <N或Y <N的板上,因为这将需要至少两个皇后以相同的等级或档位结束,因此他们会互相攻击。如果您读过n皇后问题,您将很快了解到,对于N> 3,总是可以将N个皇后放在NxN板上。现在,我们知道答案是否定的(X <N或Y <N) (X> = N并且Y> = N,N> 3)为是。剩下的就是特殊情况:

  • N = 1(是)
  • N = 2(对于X> = 2和Y> 2,是,反之亦然)
  • N = 3(对于X> = 3和Y> 3,是,反之亦然)

因此,现在我们不错的递归函数变成了一个简单的函数,它仅将N与X和Y进行比较并返回固定结果。从性能的角度来看,这是很棒的,因为您可以在固定时间内获得答案。从编程的角度来看并不是那么好,因为在这一点上,您意识到真正的问题更多是关于如何解决难题的问题,而不是关于编写递归函数的能力。

(天哪,天哪,我真的希望我在聪明的裤子回答中不要犯一些愚蠢的错误。;-)


That's great from a performance point of view, since you can get an answer in constant time. It's not so great from a programming point of view because you realize, at this point, that the question is really more about how well you can solve puzzles than it is about your ability to write a recursive function.我实际上认为面试官正在等待O(1)解决方案,因为它最终会更好,而且对许多人来说并不明显。在所有编程课程中,nxn皇后问题都作为递归的练习-许多人在再次看到该问题时不会更深入地思考。
Sopel

4

如果面试官要求您为该问题编写代码,那么我认为这是不公平的。该算法需要工作。但是,如果您的想法是向面试官展示您需要使用的类,方法或某些概念或类似的东西,那么这可能是一个公平的问题。

该问题是经典的计算机科学问题,许多此类书籍都对此进行了讨论。在这里可以找到很好的解释,其中包含动画和12种不同的解决方案以及一些代码:

http://en.wikipedia.org/wiki/Eight_queens_puzzle

也可以在这里找到代码:http : //www.codeproject.com/KB/java/EightQueen.aspx

正如我所说,不要为此感到难过,这不是一件容易的事。


0

确实,这更多是评论,但不适合其中...

一个国际象棋棋盘有8x8的正方形,且不少于8个(这些问题总是用定制的国际象棋棋盘的方法使我烦恼)。

但是无论如何,如果您有一个x * y的棋盘,并且有n个皇后,并以皇后“占领” 这些字段

在此处输入图片说明

您能否创建一个二维数组并“标记”一位女王攻击的所有字段。然后放置另一个(从板子中间开始),标记其余字段,依此类推……直到您运行任何一个字段或皇后区。

当然,这是一种非常简化的方法,因为如果定位不正确,我收集到的皇后数量将有所不同。

嗯,刚才也发现了-8个皇后问题。


我最初提出了这种精确的算法,但考虑到您不能保证如果采用这种方法,最终没有地方放您真正确定不可能的最后一个皇后。您仅消除了该特定安排。这基本上是最邻近启发法的一种应用。
受访者

@Interviewee-是的,我知道。这只是我想到的事情。如前所述,这是一个有趣的问题,可能会得到改善,但是在凌晨4点(此处),我懒得思考。顺便说一句,面试是如何进行的?
Rook

@Interviewee,这是正确的想法。缺少的部分是,如果您发现最后一个皇后没有位置,您可以备份并尝试倒数第二个皇后的其他位置。如果没有那个皇后的位置可以放置最后一个皇后,则可以备份另一个级别,然后为另一个皇后尝试另一个位置,依此类推。
Caleb

我喜欢您的头像是一副棋子:)
沃伦

0

基本上,回溯算法的工作原理如下:

  1. 创建一个X by Y数组。将所有正方形设置为空。

  2. 将女王计数设置为零。

  3. 将当前位置设置为(1,1)

  4. 看看是否可以在当前位置放置一个女王。

  5. 如果可以,请将Array(X,Y)设置为皇后,增加皇后计数。如果放置了所有皇后,请停止,您有解决方案。

  6. 如果当前位置不是(X,Y),则增加当前位置并转到步骤4。

  7. 在最后一个位置找到皇后(按照增加位置的顺序最后一个)。将当前位置设置为该皇后的位置,将其删除,然后减少皇后计数。

  8. 如果皇后计数为零,请停止,没有解决方案。

  9. 增加当前位置。

  10. 转到步骤4。


在本说明中,该算法无法正确回溯:它仅删除了最后一个可放置的女王/王后;您可能会冒险不尝试在其他位置使用更早的女王。
卡斯珀·范·登·伯格

@KaspervandenBerg算法正确回溯。我会直接回应您的批评,但老实说我无法理解。我不知道您所说的“最后一位女王”是什么意思。它只会删除最后放置的皇后,但是一旦删除后的女王放置,任何女王都可以成为最后放置的女王。它将根据需要进行回溯,以与放置皇后相反的顺序移除皇后。
David Schwartz

0

除其他答案外:创建二维数组只会使代码复杂化。

您只需要一个大小为8的向量即可构成一个普通的棋盘。如果像C 1st位是0,则为8 + 1,只是为了简化代码,而处理1-8而不是0-7。

如果您认为x是您在数组中的位置,而y是该位置的内容。例如board [1] = 8表示第一个皇后在[1,8]。

这样,您只需要检查列验证即可。

在上大学的时候,我遇到了一本非常古老的书(60年代?),它讲述了在Dartmouth BASIC中实现的算法,该书使用了尽可能少的内存来实现8皇后问题(因为年代久远,很有意义)。

据我所记得,它使用了向量思想,并且本质上以两个FOR循环强行强制执行板上的所有位置。为了检查位置的有效性,它使用了第三个循环,每个位置的WHILE循环都返回到向量中,并检查是否相等,或者使用切线运算的公式检查对角线。

可悲的是,我忘了那本书。

所述算法找到了n-queen问题的所有解。


0

如果您只需要编写一种算法来确定是否存在这种安排,那么请看一下现有的研究:
Wikipedia上的八个皇后难题

如果N> min(X,Y),则可以简单地返回false。
阅读该页面后,您知道如果N <= min(X,Y)和2,3!= min(X,Y),则返回true。

剩下2、3 == min(X,Y)和N <= min(X,Y)。

好吧,如果N <min(X,Y),找到一个解决方案很简单。
如果N == min(X,Y),则只有max(X,Y)> N时才有解决方案。

f(X, Y, N)
    if X < Y => f(Y, X, N)
    if Y > N => false
    => (Y < N) or (Y != 2 and Y != 3) or (X > N)

0

如果N> min(X,Y),显然没有解决方案。否则,您可以轻松地显示出对于N = X = Y = 2,N = X = Y = 3没有解决方案。对于所有其他情况,似乎都有解决方案。解决方案的数量似乎随着N的增加而增加。

您可以通过带回溯的详尽搜索找到解决方案:在第一行第一列中放置一个女王/王后,在第一行中女王/王后无法到达的第一列中/第二王后。在第二行等中放置一个女王/王后。如果不能将女王/王后放入k行,则将其删除,然后将k-1行中的女王/王后移至下一个未占用位置。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.