運用実績
コードは次のとおりです
1 #include <bits / stdc ++。H> 2 名前空間std を使用 ; 3 const int MAX = 1024 ; 4 const char * LINE32 = " --------------------- ----------- " ; 5 const bool PRINT_DETAILS = false ; 6 long long n、cnt = 0 ; // nはクイーンの数を表し、cntはソリューションの数を表す7 int vis [ 3 ] [ 2 * MAX + 1 ]; 8 // V [0] []、V [1] []、V [2] [] 副対角線クイーンがある場合、列を表し、主対角線は、 9 @ 0手段なしクイーン、非ゼロを示し はい、v [0] [4] = 2は、4列目の2行目にクイーンが存在することを意味します10 11 void print(){ 12 cout << LINE32 << endl; 13 cout << " 第" << cnt << " 解決策:" << endl; 14 for(int i = 1 ; i <= n; i ++ ){ 15 if(i!= 1 ){ 16 cout << " 、" ; 17 } 18 cout << " (" << vis [ 0 ] [i] << " 、" << i << " )" ; 19 } 20 cout << endl; 21 for(int i = 1 ; i <= n; i ++ ){ 22 for(int j = 1 ; j <= n; j ++ ){ 23 if(vis [ 0 ] [j]!= i){ 24 cout < < ' x ' ; } else { 26 cout << ' Q ' ; 27 } 28 } 29 cout << endl; 30 } 31 } 32 33 bool check(int row、int col){ // 座標が(row、col)にあるかどうかを確認Place queen 34 return!(Vis [ 0 ] [col] || vis [ 1 ] [row-col + n] || vis [ 2 ] [row + col]); 35 } 36 void place(int x、int y、int * r2c){ // 女王を(x、y)の位置に配置します 37 vis [ 0 ] [y] = x; 38 vis [ 1 ] [x-y + n] = vis [ 2 ] [x + y] = 1 ; 39 r2c [x] = y; 40 } 41 void remove(int x、int y){ // (x、y)の位置にあるクイーンを削除する 42 vis [ 0 ] [ y] = vis [ 1 ] [x-y + n] = vis [ 2 ] [x + y] = 0 ; 43 } 44 void solve(int n){ // 非再帰的な実装1との違いは、A。がvis [3] []を使用して判断を高速化すること、B。バックトラックの特定の操作がvis [3] []ではなく 45 int on r2c [] r2c [n + 5 ]; // 各行が配置される列 の数は、実際には再帰実装1および非再帰実装1で使用されるクイーン[]と同様です46 r2c [ 0 ] = 0 ; // ここで初期化すると、次のループを終了するときに配列が範囲外になります。影響を受けるコードは63_42 47 int row = 1、col = 1 ; 48 place(row、col、r2c); 49 row = 2 ; // in次に、配置(1,1)女王の位置とが配置されて2行目の位置を探して開始するループに入る 50 ながら(行> 0){ // 最後の行の値は0です。すべての条件がチェックされると、最初の行がトレースバックされ、行の値は0 51 if(row> n){ 52 // ソリューションを見つけてから、トレースアップする必要があるためです。 :前の行から女王を削除し、前の行の次の列から女王を配置しようとします 53 cnt ++ ; 54 if (PRINT_DETAILS){ 55 print(); 56 } 57 row--; // 行は前の行に戻ります 58 remove(row、r2c [row]); // 前の行のクイーンを削除 59 col = r2c [row] + 1 ; // このときの(row、col)は、 60 を配置する次の試行の位置です } else if(col> n){ 61 // 現在の行のすべての位置が試行されて配置され、バックトラック 62 row-- ; 63 remove(row、r2c [row]); 64 col = r2c [row] + 1 ; 65 } else if (check(row、col)){ 66 // 一致する位置を見つける 67 place(row、col、r2c); // クイーンを配置する 68 row ++; // 次の行が配置される位置を見つける 69 col = 1 ; // そして最初の列から 70を挿入 } else { 71 // この列は一致しません 。次の列を見つけます72 col ++ ; 73 } 74 } 75 } 76 77 int main(){ 78 // input 79 cout << " Enter the number of queens:" ; 80 cin >> n; 81 / / 計算 82 clock_t begin = clock(); 83 solve(n); 84 clock_t end = clock(); 85 // 出力 86 cout << LINE32 << endl; 87 cout << n << " クイーン全体の問題" << cnt << " ソリューション" << endl; 88 cout << LINE32 << endl; 89 cout << " バックトラッキング非再帰アルゴリズム実装2ソリューション" << n << " 時間のかかる女王の問題" << / * end-begin << "Dot" << * /(double)(end-begin)/ CLOCKS_PER_SEC << " s " << endl; 90 return 0 ; 91 } 92 // 14 3〜5秒
バックトラッキングアルゴリズム実装との比較2
2つの動作条件を達成するための後方再帰アルゴリズム
2つの動作条件を達成するための非再帰的アルゴリズムのバックトラック
非再帰的な実装は、少し予測できない再帰的な実装よりも少し遅いです。