fork download
  1. // Much shorter than the version below;
  2. // uses C++11 threads to parallelize the computation; also uses backtracking
  3. // Outputs all solutions for any table size
  4. #include <vector>
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <thread>
  8. #include <future>
  9.  
  10. // Print table. 'pos' is a vector of positions – the index in pos is the row,
  11. // and the number at that index is the column where the queen is placed.
  12. static void print(const std::vector<int> &pos)
  13. {
  14. // print table header
  15. for (int i = 0; i < pos.size(); i++) {
  16. std::cout << std::setw(3) << char('a' + i);
  17. }
  18.  
  19. std::cout << '\n';
  20.  
  21. for (int row = 0; row < pos.size(); row++) {
  22. int col = pos[row];
  23. std::cout << row + 1 << std::setw(3 * col + 3) << " # ";
  24. std::cout << '\n';
  25. }
  26.  
  27. std::cout << "\n\n";
  28. }
  29.  
  30. static bool threatens(int row_a, int col_a, int row_b, int col_b)
  31. {
  32. return row_a == row_b // same row
  33. or col_a == col_b // same column
  34. or std::abs(row_a - row_b) == std::abs(col_a - col_b); // diagonal
  35. }
  36.  
  37. // the i-th queen is in the i-th row
  38. // we only check rows up to end_idx
  39. // so that the same function can be used for backtracking and checking the final solution
  40. static bool good(const std::vector<int> &pos, int end_idx)
  41. {
  42. for (int row_a = 0; row_a < end_idx; row_a++) {
  43. for (int row_b = row_a + 1; row_b < end_idx; row_b++) {
  44. int col_a = pos[row_a];
  45. int col_b = pos[row_b];
  46. if (threatens(row_a, col_a, row_b, col_b)) {
  47. return false;
  48. }
  49. }
  50. }
  51.  
  52. return true;
  53. }
  54.  
  55. static std::mutex print_count_mutex; // mutex protecting 'n_sols'
  56. static int n_sols = 0; // number of solutions
  57.  
  58. // recursive DFS backtracking solver
  59. static void n_queens(std::vector<int> &pos, int index)
  60. {
  61. // if we have placed a queen in each row (i. e. we are at a leaf of the search tree), check solution and return
  62. if (index >= pos.size()) {
  63. if (good(pos, index)) {
  64. std::lock_guard<std::mutex> lock(print_count_mutex);
  65. print(pos);
  66. n_sols++;
  67. }
  68.  
  69. return;
  70. }
  71.  
  72. // backtracking step
  73. if (not good(pos, index)) {
  74. return;
  75. }
  76.  
  77. // optimization: the first level of the search tree is parallelized
  78. if (index == 0) {
  79. std::vector<std::future<void>> fts;
  80. for (int col = 0; col < pos.size(); col++) {
  81. pos[index] = col;
  82. auto ft = std::async(std::launch::async, [=]{ auto cpos(pos); n_queens(cpos, index + 1); });
  83. fts.push_back(std::move(ft));
  84. }
  85.  
  86. for (const auto &ft : fts) {
  87. ft.wait();
  88. }
  89. } else { // deeper levels are not
  90. for (int col = 0; col < pos.size(); col++) {
  91. pos[index] = col;
  92. n_queens(pos, index + 1);
  93. }
  94. }
  95. }
  96.  
  97. int main()
  98. {
  99. std::vector<int> start(12); // 12: table size
  100. n_queens(start, 0);
  101. std::cout << n_sols << " solutions found.\n";
  102. return 0;
  103. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
In file included from /usr/include/c++/5/thread:35:0,
                 from prog.cpp:7:
/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
 #error This file requires compiler and library support for the \
  ^
prog.cpp: In function 'bool threatens(int, int, int, int)':
prog.cpp:34:6: error: 'abs' is not a member of 'std'
   or std::abs(row_a - row_b) == std::abs(col_a - col_b); // diagonal
      ^
prog.cpp:34:33: error: 'abs' is not a member of 'std'
   or std::abs(row_a - row_b) == std::abs(col_a - col_b); // diagonal
                                 ^
prog.cpp: At global scope:
prog.cpp:55:13: error: 'mutex' in namespace 'std' does not name a type
 static std::mutex print_count_mutex; // mutex protecting 'n_sols'
             ^
prog.cpp: In function 'void n_queens(std::vector<int>&, int)':
prog.cpp:64:4: error: 'lock_guard' is not a member of 'std'
    std::lock_guard<std::mutex> lock(print_count_mutex);
    ^
prog.cpp:64:20: error: 'mutex' is not a member of 'std'
    std::lock_guard<std::mutex> lock(print_count_mutex);
                    ^
prog.cpp:64:37: error: 'print_count_mutex' was not declared in this scope
    std::lock_guard<std::mutex> lock(print_count_mutex);
                                     ^
prog.cpp:64:54: error: 'lock' was not declared in this scope
    std::lock_guard<std::mutex> lock(print_count_mutex);
                                                      ^
prog.cpp:79:15: error: 'future' is not a member of 'std'
   std::vector<std::future<void>> fts;
               ^
prog.cpp:79:15: error: 'future' is not a member of 'std'
prog.cpp:79:34: error: template argument 1 is invalid
   std::vector<std::future<void>> fts;
                                  ^
prog.cpp:79:34: error: template argument 2 is invalid
prog.cpp:82:9: error: 'ft' does not name a type
    auto ft = std::async(std::launch::async, [=]{ auto cpos(pos); n_queens(cpos, index + 1); });
         ^
prog.cpp:82:94: error: expected primary-expression before ')' token
    auto ft = std::async(std::launch::async, [=]{ auto cpos(pos); n_queens(cpos, index + 1); });
                                                                                              ^
prog.cpp:83:4: error: 'fts' was not declared in this scope
    fts.push_back(std::move(ft));
    ^
prog.cpp:83:18: error: 'move' is not a member of 'std'
    fts.push_back(std::move(ft));
                  ^
prog.cpp:83:28: error: 'ft' was not declared in this scope
    fts.push_back(std::move(ft));
                            ^
prog.cpp:86:20: error: ISO C++ forbids declaration of 'ft' with no type [-fpermissive]
   for (const auto &ft : fts) {
                    ^
prog.cpp:86:25: warning: range-based 'for' loops only available with -std=c++11 or -std=gnu++11
   for (const auto &ft : fts) {
                         ^
prog.cpp:86:25: error: 'fts' was not declared in this scope
prog.cpp:87:7: error: request for member 'wait' in 'ft', which is of non-class type 'const int'
    ft.wait();
       ^
stdout
Standard output is empty