n_queens_solution.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 //
5 // accompanying file LICENSE_1_0.txt or copy at
7 //=======================================================================
15 #ifndef PAAL_N_QUEENS_SOLUTION_HPP
16 #define PAAL_N_QUEENS_SOLUTION_HPP
17
18 #include "paal/utils/irange.hpp"
19
20 #include <boost/iterator/counting_iterator.hpp>
21 #include <boost/range/iterator_range.hpp>
22 #include <boost/range/numeric.hpp>
23
24 #include <vector>
25
26 namespace paal {
27 namespace local_search {
28
35 template <typename NQueensPositionsVector> struct n_queens_solution_adapter {
36  typedef typename boost::counting_iterator<int> QueensIterator;
37
44  : m_queen_position(pos),
45  m_numeber_attacing_diagonal_negative(boost::distance(pos), 0),
46  m_numeber_attacing_diagonal_nonnegative(boost::distance(pos), 0),
47  m_numeber_attacing_counter_diagonal(2 * boost::distance(pos), 0) {
48  for (auto q : irange(boost::distance(pos))) {
49  increase(q);
50  }
51  }
52
58  QueensIterator begin() const { return QueensIterator(0); }
59
65  QueensIterator end() const {
66  return QueensIterator(m_queen_position.size());
67  }
68
75  void swap_queens(int xLeft, int xRight) {
76  int leftPosition = m_queen_position[xLeft];
77  put_queen(xLeft, m_queen_position[xRight]);
78  put_queen(xRight, leftPosition);
79  }
80
89  int get_num_attacing(int x, int y) const {
90  return m_numeber_attacing_counter_diagonal[x + y] + get_diagonal(x, y);
91  }
92
100  int get_y(int x) const { return m_queen_position[x]; }
101
107  int obj_fun() const {
108  auto attacingNr = [](int sum, int n) { return sum + n * (n - 1) / 2; };
109  int sum = boost::accumulate(m_numeber_attacing_counter_diagonal, 0,
110  attacingNr);
111  sum = boost::accumulate(m_numeber_attacing_diagonal_negative, sum,
112  attacingNr);
113  return boost::accumulate(m_numeber_attacing_diagonal_nonnegative, sum,
114  attacingNr);
115  }
116
117  private:
118
125  void put_queen(int x, int y) {
126  decrease(x);
127  m_queen_position[x] = y;
128  increase(x);
129  }
130
138  int &get_diagonal(int x) { return get_diagonal(x, m_queen_position[x]); }
139
148  int &get_diagonal(int x, int y) {
149  if (x >= y) {
150  return m_numeber_attacing_diagonal_negative[x - y];
151  } else {
152  return m_numeber_attacing_diagonal_nonnegative[y - x];
153  }
154  }
155
164  int get_diagonal(int x, int y) const {
165  if (x >= y) {
166  return m_numeber_attacing_diagonal_negative[x - y];
167  } else {
168  return m_numeber_attacing_diagonal_nonnegative[y - x];
169  }
170  }
171
177  void decrease(int x) {
178  --m_numeber_attacing_counter_diagonal[x + m_queen_position[x]];
179  --get_diagonal(x);
180  }
181
187  void increase(int x) {
188  ++m_numeber_attacing_counter_diagonal[x + m_queen_position[x]];
189  ++get_diagonal(x);
190  }
191
192  NQueensPositionsVector &m_queen_position;
193  std::vector<int> m_numeber_attacing_diagonal_negative;
194  std::vector<int> m_numeber_attacing_diagonal_nonnegative;
195  std::vector<int> m_numeber_attacing_counter_diagonal;
196 };
197
198 }
199 }
200
201 #endif // PAAL_N_QUEENS_SOLUTION_HPP
QueensIterator begin() const
begin of the queens positions&#39; collection
Adapts vector representing n queen problem to class able to efficiently compute gain of given move...
auto irange(T begin, T end)
irange
Definition: irange.hpp:22
int obj_fun() const
computes total number of conflicts on the board