68 explicit NQueensState(
const size_t size = 0)
72 used_columns(
size, 0),
73 used_diag_down(
size == 0 ? 0 : 2*
size - 1, 0),
74 used_diag_up(
size == 0 ? 0 : 2*
size - 1, 0)
87 using State = NQueensState;
92 bool is_goal(
const State &state)
const
94 return state.row == n;
98 void apply(State &state,
const Move &move)
const
100 const size_t row = state.row;
101 const size_t down = row + state.n - 1 - move.col;
102 const size_t up = row + move.col;
104 state.queens[row] =
static_cast<int>(move.col);
105 state.used_columns[move.col] = 1;
106 state.used_diag_down[
down] = 1;
107 state.used_diag_up[
up] = 1;
112 void undo(State &state,
const Move &move)
const
115 const size_t row = state.row;
116 const size_t down = row + state.n - 1 - move.col;
117 const size_t up = row + move.col;
119 state.queens[row] = -1;
120 state.used_columns[move.col] = 0;
121 state.used_diag_down[
down] = 0;
122 state.used_diag_up[
up] = 0;
126 template <
typename Visitor>
127 bool for_each_successor(
const State &state,
Visitor visit)
const
132 for (
size_t col = 0; col < n; ++col)
134 const size_t down = state.row + state.n - 1 - col;
135 const size_t up = state.row + col;
136 if (state.used_columns[col]
or state.used_diag_down[
down]
or state.used_diag_up[
up])
147std::string
signature(
const NQueensState &state)
150 for (
size_t row = 0; row < state.n; ++row)
151 s.push_back(
static_cast<char>(
'0' + state.queens[row]));
157 for (
size_t row = 0; row < state.n; ++row)
159 for (
size_t col = 0; col < state.n; ++col)
160 std::cout << (state.queens[row] ==
static_cast<int>(col) ?
'Q' :
'.');
169 constexpr size_t n = 4;
176 auto result = Search::backtracking_search(NQueensDomain{n},
181 std::cout <<
"N-Queens reference example\n";
182 std::cout <<
"Board size: " << n <<
'\n';
183 std::cout <<
"Solutions found: " << result.stats.solutions_found <<
'\n';
184 std::cout <<
"Visited states: " << result.stats.visited_states <<
'\n';
185 std::cout <<
"Solution signatures:";
186 for (
auto it =
collector.solutions().get_it(); it.has_curr(); it.next_ne())
187 std::cout <<
' ' <<
signature(it.get_curr().state);
190 if (result.found_solution())
192 std::cout <<
"First solution signature: "
193 <<
signature(result.best_solution.get().state) <<
'\n';
194 std::cout <<
"First solution board:\n";
Umbrella header for the implicit state-space search framework.
Simple dynamic array with automatic resizing and functional operations.
Recursive depth-first backtracking over an implicit state space.
Collector that stores accepted solutions in an Aleph list.
User-facing facade exported by the umbrella search header.
size_t size(Node *root) noexcept
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
Exploration controls shared across engines.
bool stop_at_first_solution
Stop when the first goal is found.
Dynamic array container with automatic resizing.