これは基本的にエイトクイーンの問題ですが、1Dアレイでブルートフォースで解決します。サイズが8で、要素の範囲が0から7の配列(bという名前)があるとします。
次のように、配列内の各インデックスを8つのforループで初期化します。
int b[8]={0};
int count = 0;
for(b[0] = 0; b[0]<8; b[0]++){
for(b[1] = 0; b[1]<8; b[1]++){
for(b[2] = 0; b[2]<8; b[2]++){
for(b[3] = 0; b[3]<8; b[3]++){
for(b[4] = 0; b[4]<8; b[4]++){
for(b[5] = 0; b[5]<8; b[5]++){
for(b[6] = 0; b[6]<8; b[6]++){
for(b[7] = 0; b[7]<8; b[7]++){
if(check(b))
{
count++;
print(b, count);
}
}}
}}
}}
}}
このプログラムが行うことになっているのは、0から7までの数字のすべての組み合わせをチェックし、特定の条件に対してのみtrueを返すことです。92の解決策があるはずですが、これがおなじみのように聞こえるなら、そうあるべきです-それは力ずくの力を使った8クイーンの問題です。ここから、これが条件であると私が理解していることです。
配列に連続した数字の文字列があるかどうかを確認できるようにしたい。そのような:
[0 | 5 | 7 | 1 | 2 | 3 | 6 | 4]
ここで、要素b [3]、b [4]、およびb[5]は連続しています。数字の連続した文字列があるので、私はそれを望んでいません、私はfalseを返したいです(基本的に女王は攻撃しています)
また、次のような逆方向に連続する数字の文字列を持つ配列は必要ありません。
[0 | 5 | 7 | 3 | 2 | 1 | 6 | 4]
そして最後に、インデックスに2つ以上の数値を入れて、それらの間の数値を変更しただけで連続して見えるようにしたくありません。
[0 | 2 | 4 | 6 | 1 | 3 | 5 | 7]
b[0]とb[7]は「連続インデックス」の数値であるため、上記は受け入れられません(少なくとも2つのクイーンが互いに攻撃しているため)。
[6 | 1 | 3 | 0 | 4 | 7 | 5 | 2]
b[1]とb[4]も連続したインデックスにあるため、上記も受け入れられません。
同様に、値が交換されると、配列
[7 | 2 | 4 | 6 | 1 | 3 | 5 | 0]
[6 | 4 | 3 | 0 | 1 | 7 | 5 | 2]
また、受け入れられません。また、同じ番号を2つ以上持つことはできません。
私が抱えている問題は、チェック関数の作成にあります。1つのforループと1つのif-thenステートメントを使用する必要があると言われました。チェック関数は配列全体をそのまま取得できますか?もしそうなら、配列の右端の要素をどのように見て、連続したインデックスがあるかどうかを確認します(クイーンが攻撃しています)?私はこれを試しました:
bool ok(int board[8]){
for(int c = 7; c >= 0; c--){ //row check
for (int j=0; j<c; j++){
if (board[c]==board[j]){
return false;
}
}
for(int i = 1; i <= c; i++){
// diagonal check from top left to bottom right
if ((board[c]-i >= 0) && (board[c-i] == board[c]-i))
{return false;}
if ((board[c]+i <= 7) && (board[c+i] == board[c]+i))
{return false;}
// diagonal check from bottom left to top right
if ((board[c]-i >= 0) && (board[c-i] == board[c]+i))
{return false;}
if ((board[c]+i <= 7) && (board[c+i] == board[c]-i))
{return false;}
}
}
return true;
}
しかし、これは機能しないだけでなく(300以上のソリューションが得られます)、私が言われているほど小さくはありません。