この問題は、古典的なUSACOのDFSで、私は、少なくとも7ヶ月会った時。
チェス盤のn * n個にn個のクイーンを置く、彼らはお互いに(行、列、対角線)を食べて、そしていくつかの振り子方法を尋ねたことができませんか?DFSを考える(自己DPの絵があるとは思いません)。さて、最初に列挙するかを決定することは、i行目で、境界は私はあなたが同じマークの付いた同じ行と列を置くためにこの点を置くことができるならば、取る、その後、続けることができるかどうかを判断するために、行のn + 1、j列目、次のサイクルが検索され検索、バック、マークを消去します。ここでは、二次元のマーキングフラグを設定するフラグ[1]〜[J] = 1、フラグ[2] [iが+ J] = 1、フラグ[I-J + 1、N] = 1
1.dfsのみ行と列を解決することができ、この場合には、それを明確にするものを列挙し、これだけの行または列の上に金を保持
2.対角表現:x + yは右上の左下と同じであるが、X-Yは、取得する右下のと同じです
3.とても遅い、ブールフラグが継続することはできません表示されていない場合、ポイントのマークに直撃の時間複雑性を考えてみましょう
コード
1の#include <iostreamの> 2の#include <cstdioを> 3の#include < ストリング > 4の#include <CStringの> 5の#include <アルゴリズム> 6の#include <cmath> 7 使って 名前空間STD。 8 INT [ 50 ]。 9 のintフラグ[ 50 ] [ 50 ]。 10 INT N。 11 int型 CNT = 0 。 12の ボイド DFS(int型 I){ // 枚举到了第iが行き 13の 場合(I> N-){ // 端 14 CNT ++ ; 15 IF(CNT <= 3 ){ 16 のために(INT I = 1 ; I <= N - 、Iは++){ // 各自動的に更新 。17 COUT << A [I] << " " ; 18である } 19。 COUT << ENDL; 20である } 21が 戻り、 22は } 23である ため(INT J = 1。 ; J <= N; J ++ ){ 24 IF(のフラグ[1 ] [j] == 0 &&フラグ[ 2 ] [iが+ J] == 0 &&フラグ[ 3 ] [I-J + N] == 0 ){ 25 [i]は= J。 26 フラグ[ 1 ] [j]は= 1 。 27 フラグは、[ 2 ] = [Iは、J +] 1。// 对角线 28 フラグ[ 3 ] [I-J + N] = 1 。 29の DFS(I + 1 )。 30 フラグ[ 1 ] [j]は= 0 。 31 フラグ[2 ] [iがj] = + 0 。 32 フラグ[ 3 ] [I-J + N] = 0 ; 33 } 34 } 35 } 36 INT メイン(){ 37 CIN >> N。 38の DFS(1 )。 39 coutの<< CNT。 40 }