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

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


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

   Nクイーン問題とは、N×Nマスの盤上で互いの利き筋に当たらないようなN個のクイーンの配置を見つける問題である。クイーンは、縦・横・斜めのいずれか一方向にどこまでも移動することができ、一度に移動できる範囲をクイーンの利き筋という。8×8マスの盤上の行5列6に配置したクイーンの利き筋を、図1に示す。また、8×8マスの場合のNクイーン問題の解の一つを図2に示す。  なお、Nクイーン問題の解は存在しないこともあるし、複数存在することもある。
応用情報技術者試験(平成24年度 秋期 午後 問02 図01)
 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 図02)
応用情報技術者試験(平成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である。
応用情報技術者試験(平成24年度 秋期 午後 問02 図07)
応用情報技術者試験(平成24年度 秋期 午後 問02 図08)

設問1

NxNマスの場合、本文及び図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クイーン、バックトラック、配列設計、対角線、再帰探索

設問2

NxNマスの場合、本文及び図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 の範囲で扱えば整合します。

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

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

(1)図7中のに入れる適切な字句を答えよ。

模範解答

ウ:k エ:l オ:N カ:posi ← k キ:i+1

解説

解答の論理構成

  1. ループ変数
    図7には
    if ( colk と upwd[i+k-1] と downwd[ ... ] … )
    とあり、配列添字に使われているのは 「k」 だけです。従ってループで増減させる変数も 「k」 とするのが自然です。
  2. ループ開始値
    解法の手順には
    「1行目において、1列目にクイーンを配置する。次に…2行目の列を1列目から順に探索し…」
    とあります。列探索は必ず 「1列目から」 始めると明記されているため、開始値は 「1」 です。
  3. ループ終了値
    N×N 盤の全列を調べきるまで探索を続けるため、終了値は最大列番号である 「N」 です。
  4. クイーンを配置した列を記録する
    配列 pos の定義は
    「行番号を添字とし、その行に配置したクイーンの位置(列番号)を値とする」
    ですから、行 i にクイーンを置いた列 k を格納する代入文は
    posi ← k となります。
  5. 次の行を再帰探索する
    1 行に 1 個ずつクイーンを置く方針なので、行 i の次は 「i+1 行目」 を探索します。したがって再帰呼び出しの実引数は 「i+1」 です。

誤りやすいポイント

  • 変数名の取り違え
    k と i を混同し、列探索を i で回してしまうと行番号と列番号が逆転します。
  • ループ開始値の誤記
    「列1から探索」という文面を読み落として 0 から開始すると、配列外参照や列番号ずれを起こします。
  • pos の更新忘れ
    クイーンを配置した時点で posi を更新しないと、バックトラック後に正しい出力が得られません。

FAQ

Q: ループ変数を c など他の文字にしてはいけませんか?
A: ソースコード自体は任意名で動きますが、問題文が colk など 「k」 を前提に説明しているため、解答欄には一致させる必要があります。
Q: i+1 でなく ++i でも良いですか?
A: 再帰呼び出しの実引数としては「次の行番号」の値そのものが必要です。++i は呼び出し後の i を変更してしまう恐れがあるため、問題の意図に合わせて i+1 を使います。
Q: 0 オリジンで実装するときの添字計算はどう直せばよいですか?
A: 行・列を 0〜N-1 とする場合、upwd の添字は i+k、downwd は i-k+N-1 など、すべての式を 1 だけ減算または加算して整合を取ります。

関連キーワード: バックトラック、再帰呼出し、探索アルゴリズム、配列インデックス、Nクイーン

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

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

模範解答

ク:l

解説

解答の論理構成

  1. 【問題文】には最初の作業として
    「・1行目において、1列目にクイーンを配置する。」
    と明記されています。したがって探索は“行1”から始まります。
  2. 図7の関数 search(i) は「i行目以降についてクイーンの配置の仕方を探索する」手続きです。
    つまり、行1から探索を開始したい場合は i = 1 を与えます。
  3. 図8のメインプログラムでは
    if ( search( ) と SUCCESS が等しい ) then
    と書かれており、ここに渡す値が“開始行”になります。
  4. 以上より には 1 を入れ、search(1) として探索を開始するのが論理的帰結です。
  5. よって解答は
    「ク:1」

誤りやすいポイント

  • 0 行目や N 行目から探索を始めると考えてしまう
    → 配列添字を 0 起点で実装する言語に慣れていると誤解しやすいですが、本問題では【問題文】が「1行目」からの記述です。
  • pos 配列の初期値が 0 なので「行番号も 0 から」と連想してしまう
    → pos の 0 は「未配置」を表す特別値であって行番号ではありません。
  • search の呼出しで変数を渡すと誤認する
    → 図8には引数として変数名は示されておらず、固定値を渡す想定です。

FAQ

Q: 行番号を 0 起点に書き換えても動きますか?
A: アルゴリズム自体は動きますが、配列添字計算(特に upwd や downwd)をすべて修正する必要があります。本試験では【問題文】が 1 起点なので、そのまま従うのが安全です。
Q: 途中で複数の解を列挙したい場合はどう変更しますか?
A: search が解を見つけた時点で戻らずに盤面を記録し、クイーンを取り除いて探索を続行するようにします。戻り値で探索終了を制御しない実装へ変えるのが一般的です。
Q: search(1) をループで呼び直せば全部の解が得られますか?
A: いいえ。search から戻る時点で盤面は初期状態へ巻き戻っているため、再度 search(1) を呼んでも同じ解しか生成されません。呼出し側ではなく search 内部で分岐を制御する必要があります。

関連キーワード: バックトラック、再帰呼出し、配列インデックス、盤面探索、斜め判定

設問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で示された ① は
// クイーンを取り除く
posi ← 0
colk ← 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 へ順に試す” という本プログラム固有の順序での結果です。

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

\ せっかくなら /

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

クイズ画面へ遷移する

すぐに利用可能!

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

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