今日のインタビューで私は次の質問をされました、そしてそれ以来ずっとそれについて考えていました。私はそれに答えることができず、解決策をオンラインで見つけることができませんでした。
寸法がX x YとNのクイーンのチェス盤を想定して、これらのクイーンを互いに攻撃できないように盤上に配置できるかどうかを判断します。
2クイーンの2 x 3ボードにはソリューションがあるため、アルゴリズムはtrueを返します。
Q . .
. . Q
たとえば、紙の上で解決する方法だけでなく、このパズルに対するプログラミングのアプローチを探しています。
これはプログラミングの観点からは(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。残っているのは特別な場合です:
したがって、ここで、Nice再帰関数は、NをXおよびYと比較して、既定の結果を返す単純な関数になります。あなたは一定の時間で答えを得ることができるので、それはパフォーマンスの観点から素晴らしいです。現時点では、問題は再帰関数を書く能力よりも、パズルをどれだけうまく解くことができるかということを理解しているため、プログラミングの観点からはそれほど優れていません。
(そして、男の子ああ、私は本当に私が私のスマーティーパンツの答えでいくつかのばかげた過ちを犯さなかったことを本当に望んでいます。;-)
インタビュアーが問題のコードを書くようにあなたに頼んだならば、それは公平ではないと思います。アルゴリズムには作業が必要です。ただし、使用する必要があるクラス、メソッド、またはいくつかの概念などをインタビュアーに示すことがアイデアである場合、それは公正な質問になる可能性があります。
問題は古典的なコンピュータサイエンスの問題であり、そのような多くの本で議論されています。アニメーションといくつかのコードを含む12の異なるソリューションの優れた説明は、次の場所にあります。
http://en.wikipedia.org/wiki/Eight_queens_puzzle
コードもここにあります: http://www.codeproject.com/KB/Java/EightQueen.aspx
言ったように、これは簡単なものではありません。
他の答えに追加してください: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-クイーン問題のすべてのソリューションを見つけました。
これは実際にはもっとコメントですが、そこには収まりません...
チェス盤には8x8のマス目があります(これらの質問は常にカスタマイズされたチェス盤のアプローチに悩まされます)。
しかし、とにかく、x * yのチェス盤とn個の女王がいて、女王がそれを「取る」 これらのフィールド の場合
2次元配列を作成し、1人の女王が攻撃するすべてのフィールドに「フラグを立てる」ことができます。次に、もう1つを(ボードの中央から)配置し、残りのフィールドにフラグを設定します。フィールドまたはクイーンのいずれかを実行するまで続きます。
もちろん、これは非常に単純化されたアプローチです。不適切な位置に配置すると、クイーンの最大数が異なるため、私はそれを収集するためです。
うーん、これも見つけた- 8クイーンの問題
そのような配置が存在するかどうかを判断するためのアルゴリズムを記述する必要がある場合は、既存の調査を見てください。
ウィキペディアの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)
N> min(X、Y)の場合、明らかに解はありません。それ以外の場合は、N = X = Y = 2、N = X = Y = 3の解がないことを簡単に示すことができます。他のすべての場合には、解があるようです。 Nが大きくなるにつれて、解の数は増えるようです。
バックトラックを使用した徹底的な検索により、解決策を見つけることができます。最初の行の列1に女王を配置します。1行目の女王が到達できない最初の列の2行目に女王を配置します。クイーンを2列目などに配置します。クイーンを行kに配置できない場合は、クイーンを削除して、列k-1のクイーンを次の空いている位置に移動します。
基本的に、バックトラックアルゴリズムは次のように機能します。
X x Y配列を作成します。すべての正方形を空に設定します。
クイーン数をゼロに設定します。
現在の位置を(1,1)に設定します
クイーンを現在の位置に配置できるかどうかを確認します。
可能であれば、Array(X、Y)をqueenに設定し、クイーン数を増やします。すべてのクイーンを配置した場合、stopが解決します。
現在の位置が(X、Y)でない場合は、現在の位置をインクリメントして、手順4に進みます。
最後の位置にある女王を見つけます(位置をインクリメントした順序で最後になる)。現在の位置をその女王の位置に設定し、それを削除して、女王の数を減らします。
クイーン数がゼロの場合stopは、解決策はありません。
現在位置をインクリメントします。
手順4に進みます。