戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

応用情報技術者 2012年 秋期 午後 問02


Nクイーン問題に関する次の記述を読んで、設問1~3に答えよ。

   Nクイーン問題とは、N×Nマスの盤上で互いの利き筋に当たらないようなN個のクイーンの配置を見つける問題である。クイーンは、縦・横・斜めのいずれか一方向にどこまでも移動することができ、一度に移動できる範囲をクイーンの利き筋という。8×8マスの盤上の行5列6に配置したクイーンの利き筋を、図1に示す。また、8×8マスの場合のNクイーン問題の解の一つを図2に示す。  なお、Nクイーン問題の解は存在しないこともあるし、複数存在することもある。
応用情報技術者試験(平成24年度 秋期 午後 問02 図1、2)
 Nクイーン問題に対し、空の盤上にクイーンを配置し、その配置したクイーンの利き筋に当たらない位置を探索しながら、行順にクイーンを配置するという、次のような解法を考えた。   〔Nクイーン問題の解法〕  ・1行目において、1列目にクイーンを配置する。次にこの1行目のクイーンの利き筋に当たらない2行目の列を1列目から順に探索し、クイーンを配置する。同様に次の行以降も、既に配置したクイーンの利き筋に当たらない列を探索し、クイーンを配置する。  ・N行目までクイーンが配置できた場合は、解の一つが見つかったとして終了する。  ・ある行でクイーンが配置できる列が見つからなかった場合は、一つ前の行に戻り、その行のクイーンを取り除く。取り除いたクイーンの次の列以降で、クイーンが配置できる列を探索する。それでも列が見つからなかった場合は、更に前の行に戻り、同様に繰り返す。  ・1行目においてもクイーンが配置できる列がなくなった場合は、このNクイーン問題の解はないということで終了する。   〔利き筋の判定〕  行i列kのマスが既に配置したクイーンの利き筋に当たるか否かを容易に判別できるよう、盤面の利き筋の方向別に配列col(列方向)、upwd(斜め上方向)及びdownwd(斜め下方向)を用意した(図3~5)。解法では、一つの行には一つしかクイーンが配置されないので、行方向の判別は行う必要がない。  各配列の要素の値は、その方向にまだクイーンが配置されていないときFREEとなり、既に配置されているときNOT_FREEとなる。各要素の初期値はFREEである。  図3~5の矢印の先の番号は、各配列の添字に対応する。N×Nマスの場合、配列colの大きさはNであり、upwdとdownwdの大きさはともにアである。
応用情報技術者試験(平成24年度 秋期 午後 問02 図3、4、5)
 例えば、図6のように8×8マスの盤上の行1列1と行2列3のマスにクイーンを配置した場合は、col[1]、col[3]、upwd[1]、upwd[4]、downwd[7] 及びdownwd[8] の値がNOT_FREEとなる。一般にN×Nマスの盤上の行i列kのマスにクイーンを配置した場合は、col[k]、upwd[i+k-1] 及びdownwd[イ]の値がNOT_FREEとなる。
応用情報技術者試験(平成24年度 秋期 午後 問02 図06)
〔Nクイーン問題の解法のプログラム〕  i行目以降についてクイーンの配置の仕方を探索する再帰関数searchのプログラムを図7に、メインプログラムを図8に示す。  関数searchはi行目以降のクイーンの配置の仕方が見つかった場合にSUCCESSを、見つからなかった場合にFAILUREを戻す。  配列posは、行番号を添字とし、その行に配置したクイーンの位置(列番号)を値とする。配置されていない場合の値は0である。

設問1:

問題文を見る
N×Nマスの場合、本文及び図7中のアに入れる適切な字句を答えよ。

模範解答

ア:2N-1

解説

解答の論理構成

  1. 問題文は「N×Nマスの場合、配列colの大きさはNであり、upwdとdownwdの大きさはともにアである。」と述べています。
  2. upwdとdownwdはそれぞれ“斜め上方向”“斜め下方向”を示す配列です。
  3. の盤面で斜め方向に走る利き筋(=対角線)は、 • 左上→右下方向:盤面右端までに 本、下端までに 本の計 本
    • 左下→右上方向:同様に計 本
    のように、それぞれ 本存在します。
  4. よって、斜め方向を表す各配列の要素数は「」でなければ全ての対角線を一意に管理できません。
  5. したがって、ア に入る字句は「2N-1」となります。

誤りやすいポイント

  • 「対角線は 本しかない」と思い込む
    → 盤面中央をはさんで上下(または左右)にもう 本あることを見落としやすいです。
  • “両方向合わせて 本”と考え、配列も倍にする
    → upwdとdownwdは方向別に1本ずつ用意されるため、各配列は で十分です。
  • 端のマスにあるクイーンを想定せず、添字範囲を ではなく など半端に設定する
    → 図中の添字は「1」から始まるため、範囲は必ず を確保する必要があります。

FAQ

Q: 添字を から始める実装にしたい場合、配列サイズはどうなりますか?
A: 0から数え上げても要素数自体は変わらないため、サイズは のままです。添字範囲は になります。
Q: という式を暗記するより良い覚え方はありますか?
A: 盤面の1本の主対角線に加えて、その上下(または左右)に対角線が1本ずつ増えるイメージを持つと自然に「主対角線1本+両側に 本=」と導けます。
Q: 盤面サイズが奇数でも偶数でも なのですか?
A: はい。対角線の本数は盤面の行・列数のみに依存し、奇数・偶数を問いません。

関連キーワード: Nクイーン、バックトラック、配列設計、対角線、再帰探索

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

N×Nマスの場合、本文及び図7中のイに入れる適切な字句を答えよ。

模範解答

イ:i-k+N

解説

解答の論理構成

  1. 斜め方向の管理用配列
    【問題文】では「盤面の利き筋の方向別に配列col(列方向)、upwd(斜め上方向)及びdownwd(斜め下方向)を用意した」とあり、各マスにクイーンを置くと3本の配列要素をNOT_FREEにします。
  2. upwdの添字規則は与えられている
    同じ文中で「upwd[i+k-1]」と添字式を明示しています。斜め上方向は行番号iと列番号kの“和”が一定であるため、i+kが基準になるのは自然です。
  3. downwdの本質は “行−列” が一定
    斜め下方向は行番号と列番号の“差” i-kが同じマスを結びます。
  4. 負値を回避するためのオフセット
    差i-kは
    • 最小で1-N(一番左上のマス)
    • 最大でN-1(一番右下のマス)
      と負の値を取り得ます。配列添字は1以上の整数でそろえたいので、定数を足してシフトします。
  5. 0ではなく N を加える理由
    • 値域1-N … N-1に N を加えると1 … 2N-1に変換できます。
    • この範囲は【問題文】の「upwdとdownwdの大きさはともにアである」から、配列長が2N-1であることと整合します。
  6. 結論
    以上より「downwd[イ]」の添字は
    i - k + N
    となり、模範解答の「イ:i-k+N」と一致します。

誤りやすいポイント

  • upwdと同じく +1オフセットを付けてi-k+N-1とずらしてしまう。
  • i-kが負になるケースを考えずにそのまま配列添字に用いて実行時エラーを起こす。
  • 差ではなく和を用いてupwdとdownwdを混同する。

FAQ

Q: なぜ +Nでなく +N-1ではだめなのですか?
A: 最小値1-Nに +N-1を足すと0になり、配列添字は1から始める前提と矛盾します。+Nを足せば下限が1になります。
Q: 配列長が2N-1であることを簡単に確認する方法は?
A: 差の取りうる値の個数はN(負側)+1(0)+N-1(正側)で計2N-1です。全てに1を足して1から2N-1の添字で管理できます。
Q: 盤面を0始まりの添字で実装したいときは?
A: その場合はupwdをi+k、downwdをi-k+(N-1) とし、配列長を2N-1のまま0〜2N-2の範囲で扱えば整合します。

関連キーワード: バックトラッキング、再帰呼び出し、配列インデックス、オフセット計算、二次元座標

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問3:〔Nクイーン問題の解法のプログラム〕について、(1)〜(3)に答えよ。

問題文を見る
(1)図7中のウ〜キに入れる適切な字句を答えよ。

模範解答

ウ:k エ:1 オ:N カ:pos[i] ← k キ:i+1

解説

解答の導き方

図7の for 文と、その中の処理を一つずつ本文の記述と突き合わせて決めます。
  1. ループ変数(ウ)
    for 文の直後の条件が「col[k] と upwd[i+k−1] と downwd[[イ]] が全て FREE と等しい」となっており、列を表す添字は k です。関数 search は i 行目について列を順に試すので、ループ変数は列番号の k です。
    → [ウ] = k
  2. 開始値(エ)と終了値(オ)
    本文は解法を「1 行目において、1 列目にクイーンを配置する。次に 2 行目において、1 列目から順に、…クイーンが配置できる列を探索する」と説明しています。各行の探索は 1 列目から始まり、本文の「N×N マスの場合、配列 col の大きさは N」のとおり列番号は 1〜N です。
    → [エ] = 1、[オ] = N
    本文の「取り除いたクイーンの次の列以降で…探索する」という動作は、開始値を変えなくても実現できます。後続の行で FAILURE が返ると①でクイーンを取り除き、同じ for 文が k を 1 増やして次の列を試すからです。
  3. クイーンを配置する処理(カ)
    本文に「配列 pos は、行番号を添字とし、その行に配置したクイーンの位置(列番号)を値とする」とあり、①では「pos[i] ← 0」で取り除いています。配置するときはその逆で、i 行目に列番号 k を記録します。
    → [カ] = pos[i] ← k
  4. 再帰呼出しの引数(キ)
    search は「i 行目以降についてクイーンの配置の仕方を探索する」関数です。i 行目に置けたら、次は i+1 行目以降を探索します。
    → [キ] = i+1

誤りやすいポイント

  • エを「前回試した列の次」を表す変数にしてしまう。再試行は for 文が k を進めることで行われるので、開始値は常に 1 です。
  • ループ変数を行番号の i と取り違える。行は search の引数 i、列は for 文の k です。
  • カで「col[k] ← NOT_FREE」を答える。この処理は図7で既にカの次の行に書かれており、カは pos の記録です。

FAQ

Q: 後戻りした行で、なぜ 1 列目から試し直さずに済むのですか?
A: 後戻りは「search(i+1) が FAILURE を返した」ときに、i 行目の for 文の途中で起こります。①でクイーンを取り除いた後、for 文はそのまま k+1 列目に進むので、既に試した列を繰り返すことはありません。
Q: pos を記録するのは何のためですか?
A: 解が見つかったとき、各行のクイーンの列番号を印字するためです。図8 では search が SUCCESS を返したときに「解となるクイーンの配置を印字する」としています。

関連キーワード: バックトラック、再帰、深さ優先探索、Nクイーン問題

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問3:〔Nクイーン問題の解法のプログラム〕について、(1)〜(3)に答えよ。

問題文を見る
(2)図8中のクに入れる適切な字句を答えよ。

模範解答

ク:1

解説

解答の導き方

図8のメインプログラムは「if ( search( [ク] ) と SUCCESS が等しい ) then」で探索を始めます。何行目から探索を始めるかを決めます。
  1. 関数 search の引数の意味
    本文に「i 行目以降についてクイーンの配置の仕方を探索する再帰関数 search」とあります。引数は探索を始める行番号です。
  2. 探索の開始位置
    本文の解法は「1 行目において、1 列目にクイーンを配置する」から始まります。盤面全体(1 行目以降)の配置を探すので、最初の呼出しでは 1 行目を指定します。
  3. 結論
    → [ク] = 1
    search(1) の中で 1 行目のクイーンを置き、search(2)、search(3)、…と再帰的に次の行へ進みます。

誤りやすいポイント

  • 0 を答える。本文の行番号・列番号は 1 から始まり、図3〜6 の配列の添字も 1 からです。
  • N を答える。search は「i 行目以降」を探索するので、N を渡すと最後の行しか探索しません。

FAQ

Q: search(1) が FAILURE を返すのはどんなときですか?
A: 1 行目のどの列にクイーンを置いても、残りの行に配置できない場合です。このとき図8 では解がないことになります。

関連キーワード: 再帰呼出し、バックトラック、Nクイーン問題

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問3:〔Nクイーン問題の解法のプログラム〕について、(1)〜(3)に答えよ。

問題文を見る
(3)4×4マスの場合、このプログラムによる解を図9に示す。この結果が得られるまでに、図7中の①の部分は何回実行されるか答えよ。 応用情報技術者試験(平成24年度 秋期 午後 問02 図09)

模範解答

4

解説

解答の論理構成

  1. 初期状態
    メインプログラム(図8)の
    if ( search( ク ) …
    でsearch(1) が呼ばれ、全配列は FREE、posは全て0です。
  2. 探索木の展開順序
    関数searchは図7の
    for ( ウ を エ から オ まで1ずつ増やす )
    で列kを 1 → 2 → 3 → 4 の順に調べます。
  3. ① が実行される条件
    図7で示された ① は
// クイーンを取り除く
pos[i] ← 0
col[k] ← FREE
upwd[i+k-1] ← FREE
downwd[ イ ] ← FREE
という “バックトラック” 部分です。
すなわち「一度置いたクイーンの後続行で FAILURE が返されたとき」に ① が1回実行されます。
  1. 4×4マスにおける実行過程
    (各行の “→” は実際にクイーンを置いた列、×は衝突で置けなかった列を表す)
    行調査順結果① 実行有無
    11→後続で失敗①④
    21× 2× 3→後続で失敗①①
    31× 2× 3× 4×全滅 → 戻る—
    23を取り除き4→後続で失敗①③
    31× 2→後続で失敗①②
    4全滅 → 戻る—
    32を取り除き 全滅—
    24を取り除き 全滅—
    11を取り除き2→以降は成功①④
    ① が実行されたタイミングは次の4回です。
    1. (2行3列) を取り除く
    2. (3行2列) を取り除く
    3. (2行4列) を取り除く
    4. (1行1列) を取り除く
  2. 結論
    以上より、図9の解に到達するまでに
    「図7中の①の部分」は 4回 実行されます。

誤りやすいポイント

  • ① は “列を1つ進めるたび” ではなく、“再帰呼び出しが FAILURE を返したときだけ” 実行されます。
  • 同じ行で複数回クイーンを置き換えても、① が走るのは “取り除くときだけ” であり、“置き直す前の衝突判定” では走りません。
  • 盤上で置ける列が0本になった行では その行では①が発生しない 点を忘れがちです(①は「置いた後」にしか現れないため)。

FAQ

Q: ① が5回以上になると考えてしまいました。どこで数え間違えやすいですか?
A: 行3で “1つも置けずにただ戻る” 場面があります。このときはクイーンを置いていないので①は呼ばれません。ここをカウントしてしまうと1回多くなります。
Q: 解が見つかったあとにも①は動きますか?
A: 図7のreturn SUCCESSが発生したら親関数もすぐreturn SUCCESSへ伝播するため、以降の①は実行されません。
Q: 別の列順(例:右から左)で探索すると①の回数も変わりますか?
A: はい。バックトラックの回数は探索順に依存します。今回の答え「4」は “列を1から4へ順に試す” という本プログラム固有の順序での結果です。

関連キーワード: バックトラック、再帰探索、状態空間木、コンビナトリック探索、配列フラグ

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

応用情報技術者を
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について