N女王、X by Y理事会決定問題インタビュー質問


10

今日のインタビューで次の質問をされて以来、ずっと考えていました。私はそれに答えることができず、解決策をオンラインで見つけることができませんでした。

寸法がX x YとNのクイーンのチェス盤を想定して、これらのクイーンを互いに攻撃できないように盤上に配置できるかどうかを判断します。

2クイーンの2 x 3ボードにはソリューションがあるため、アルゴリズムはtrueを返します。

Q . .
. . Q

たとえば、このパズルのプログラミング手法を探しています。たとえば、紙の上で解決する方法だけではありません。


他の検索ヒューリスティックと同様に、Best First Searchは確かにオプションです
Jason

2
これまでで最悪のインタビューの質問の1つにノミネートされました-彼らが取り組んでいるソフトウェアがバックトラッキングソリューションに依存している場合を除いて、それは完全に関連があります
Steven A. Lowe

1
公平に言うと、インタビュアーは、これは単なる追加のクレジットのようなものだと述べました。インタビューの残りはかなり合法的なIMOでした。ちょっと気になっただけ。
インタビュー対象者

多分それは彼が答えでカレブによって述べられた事実を使用することによって彼がバックトラックまたは(見つけることについて考える)O(1)ソリューションでシミュレーションをするかどうかのテストでした。単純なものをプログラムする能力は、仕事で必要なすべてのものではありません。
Sopel

ここでは宿題は明らかに範囲外です。
2017

回答:


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)
}

問題について少し考えると、X <NまたはY <NのボードにNクイーンを合わせる方法はないことがわかります。これは、少なくとも2つのクイーンが同じランクまたはファイルになることを必要とするためです。したがって、彼らはお互いを攻撃します。n-クイーンの問題について読むと、N x NボードにN> 3の場合にNクイーンを配置することが常に可能であることをすぐに理解できます。これで、(X <NまたはY <N)の答えはNOであることがわかります。 (X> = NおよびY> = N、N> 3)の場合はYES。残っているのは特別な場合です:

  • N = 1(はい)
  • N = 2(X> = 2およびY> 2の場合はYES、またはその逆)
  • N = 3(X> = 3およびY> 3またはその逆の場合はYES)

これで、私たちの素晴らしい再帰関数は、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クイーンの問題は、すべてのプログラミングコースに再帰の練習問題として含まれています。多くの人は、この問題をもう一度見たときに深く考えません。
ソペル2017

4

インタビュアーが問題のコードを書くようにあなたに頼んだならば、それは公平ではないと思います。アルゴリズムには作業が必要です。ただし、使用する必要があるクラス、メソッド、またはいくつかの概念、または類似のものをインタビュアーに示すことがアイデアである場合、それは公正な質問になる可能性があります。

問題は古典的なコンピュータサイエンスの問題であり、そのような多くの本で議論されています。アニメーションと12の異なるソリューションおよびいくつかのコードを含む、優れた説明がここにあります。

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

また、コードはここにあります:http : //www.codeproject.com/KB/java/EightQueen.aspx

言ったように、これは簡単なものではありません。


0

これは本当にコメントですが、そこには収まりません...

チェス盤には8x8のマス目があります(これらの質問は常にカスタマイズされたチェス盤のアプローチに悩まされます)。

しかし、とにかく、x * yのチェス盤とn人の女王がいて、女王がこれらのフィールドを取った場合、

ここに画像の説明を入力してください

2次元配列を作成し、1人の女王が攻撃するすべてのフィールドに「フラグを立てる」ことができます。次に、他の1つを(ボードの中央から)配置し、残りのフィールドにフラグを付けます。フィールドまたはクイーンのいずれかを実行するまで続けます。

もちろん、これは非常に単純化されたアプローチです。不適切な位置に配置すると、クイーンの最大数が変動するためです。

うーん、これも見つけた-8クイーンの問題。


私は最初にこの正確なアルゴリズムを提案しましたが、このアプローチを採用し、最後の女王を配置する場所がなく、本当に不可能であると判断した場合は保証されないことを考慮してください。あなたはその特定の取り決めを排除しただけです。これは基本的に、最近傍ヒューリスティックのアプリケーションです。
インタビュー対象者

@Interviewee-そうだね。これは私が頭の上から思いついたものです。言われたように、それは興味深い問題であり、おそらく改善される可能性がありますが、午前4時(ここ)で私はただ考えるのが面倒です。ところで、インタビューはどうでしたか?
2009

@インタビュー対象者、これは正しい考えです。欠けているのは、最後のクイーンの場所がないことがわかった場合、バックアップして、最後から2番目のクイーンの別の位置を試すことです。最後のクイーンを配置できるそのクイーンの場所がない場合は、別のレベルをバックアップして、最後から3番目のクイーンの別の場所を試します。
カレブ

私はあなたのアバターがチェスの駒であるのが好きです:)
warren

0

基本的に、バックトラックアルゴリズムは次のように機能します。

  1. X x Y配列を作成します。すべての正方形を空に設定します。

  2. クイーン数をゼロに設定します。

  3. 現在の位置を(1,1)に設定します

  4. クイーンを現在の位置に配置できるかどうか確認してください。

  5. 可能であれば、Array(X、Y)をqueenに設定して、クイーン数を増やします。すべてのクイーンを配置した場合、停止します。解決策があります。

  6. 現在の位置が(X、Y)でない場合は、現在の位置をインクリメントして、手順4に進みます。

  7. 最後の位置(位置をインクリメントする順序で最後になる位置)にあるクイーンを見つけます。現在の位置をその女王の位置に設定し、それを削除して、女王の数を減らします。

  8. クイーン数がゼロの場合、停止します。解決策はありません。

  9. 現在位置をインクリメントします。

  10. 手順4に進みます。


この説明では、アルゴリズムは正しくバックトラックしません。配置可能な最後のクイーンを削除するだけです。あなたは他のポジションで以前のクイーンを絶対に試さないでください。
Kasper van den Berg

@KaspervandenBergアルゴリズムは正しくバックトラックします。私はあなたの批判に直接対応しますが、正直にそれを理解することはできません。「最後の配置可能な女王」とはどういう意味かわかりません。最後に配置されたクイーンのみが削除されますが、削除後に配置されたクイーンが最後に配置されたクイーンになることができます。必要なところまでバックトラックし、配置した順序とは逆にクイーンを削除します。
David Schwartz

0

他の答えに追加してください。2次元配列を作成すると、コードが複雑になるだけです。

通常のチェス盤には、サイズ8のベクトルが必要です。または、Cのような8 + 1の場合、1番目の位置は0です。これは、コードを単純化するためだけであり、0-7ではなく1-8を扱います。

xが配列内の位置であり、yが位置の内容であると考える場合。たとえば、board [1] = 8は、最初のクイーンが[1,8]にあることを意味します。

このようにして、列の検証を確認するだけで済みます。

教員時代に、ダートマスBASICで実装されたアルゴリズムについて、可能な限り少ないメモリを使用して8クイーン問題を実装した非常に古い本(60年代?)に出会いました(古いので、それは理にかなっています)。

私が覚えている限りでは、それはベクトルのアイデアを使用しており、本質的に総当たりで2つのFORサイクルでボード内のすべてのポジションを強制しました。位置の有効性をチェックするために、3番目のループを使用し、各位置のWHILEサイクルがベクトルに戻り、等しい数をチェックするか、または正接演算を使用して式で対角線をチェックします。

悲しいことに、私はその本を見失っていました...

このアルゴリズムは、n-クイーン問題のすべてのソリューションを見つけました。


0

そのような配置が存在するかどうかを判断するためのアルゴリズムを作成する必要があるだけの場合は、既存の調査を見てください:
ウィキペディアの8つの女王パズル

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が大きくなるにつれて、解の数は増えるようです。

バックトラックを使用した徹底的な検索により、解決策を見つけることができます。最初の行の列1に女王を配置します。2行目の女王を1行目の女王が到達できない最初の列に配置します。クイーンを2列目に配置します。クイーンを列kに配置できない場合は、クイーンを削除して、列k-1のクイーンを次の空いている位置に移動します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.