2020/16
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace dlx {
|
||||
|
||||
@@ -39,8 +40,8 @@ public:
|
||||
// Increases the number of rows and columns if necessary.
|
||||
auto Set(std::size_t row, std::size_t col) -> void;
|
||||
|
||||
// Marks a column as optional: a solution need not cover the given column,
|
||||
// but it still must respect the constraints it entails.
|
||||
// Marks a column as optional: a solution need not cover the given column,
|
||||
// but it still must respect the constraints it entails.
|
||||
auto MarkOptional(std::size_t col) -> void;
|
||||
|
||||
// Removes a row from consideration.
|
||||
@@ -53,19 +54,19 @@ public:
|
||||
auto PickRow(std::size_t row) -> void;
|
||||
|
||||
auto Solve(
|
||||
std::function<void(std::size_t, std::size_t, std::size_t)> try_cb,
|
||||
std::function<void()> undo_cb,
|
||||
std::function<void()> found_cb,
|
||||
std::function<void(std::size_t)> stuck_cb) -> void;
|
||||
std::function<bool(std::size_t, std::size_t, std::size_t)> try_cb,
|
||||
std::function<bool()> undo_cb,
|
||||
std::function<bool()> found_cb,
|
||||
std::function<bool(std::size_t)> stuck_cb) -> void;
|
||||
};
|
||||
|
||||
auto ForallCover(Dlx& dlx, auto cb) {
|
||||
std::vector<std::size_t> sol;
|
||||
dlx.Solve(
|
||||
[&](std::size_t c, std::size_t s, std::size_t r) { sol.push_back(r); },
|
||||
[&](){ sol.pop_back(); },
|
||||
[&](){ cb(sol); },
|
||||
[](std::size_t){}
|
||||
[&](std::size_t c, std::size_t s, std::size_t r) { sol.push_back(r); return false; },
|
||||
[&](){ sol.pop_back(); return false; },
|
||||
[&](){ return cb(std::as_const(sol)); },
|
||||
[](std::size_t){ return false; }
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -228,43 +228,42 @@ auto Dlx::RemoveRow(std::size_t i) -> void {
|
||||
}
|
||||
|
||||
auto Dlx::Solve(
|
||||
std::function<void(std::size_t, std::size_t, std::size_t)> try_cb,
|
||||
std::function<void()> undo_cb,
|
||||
std::function<void()> found_cb,
|
||||
std::function<void(std::size_t)> stuck_cb) -> void
|
||||
std::function<bool(std::size_t, std::size_t, std::size_t)> try_cb,
|
||||
std::function<bool()> undo_cb,
|
||||
std::function<bool()> found_cb,
|
||||
std::function<bool(std::size_t)> stuck_cb) -> void
|
||||
{
|
||||
auto const recurse = [&](auto const& self) -> void {
|
||||
auto const recurse = [&](auto const& self) -> bool {
|
||||
auto c = root_->R;
|
||||
if (c == root_) {
|
||||
found_cb();
|
||||
return;
|
||||
return found_cb();
|
||||
}
|
||||
|
||||
auto s = std::numeric_limits<std::size_t>::max();
|
||||
auto s = c->s;
|
||||
for (auto const i : root_->rightwards()) {
|
||||
if (i->s < s) {
|
||||
s = (c = i)->s;
|
||||
|
||||
if (s == 0) {
|
||||
stuck_cb(c->n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s == 0) {
|
||||
return stuck_cb(c->n);
|
||||
}
|
||||
|
||||
c->CoverCol();
|
||||
for (auto const r : c->downwards()) {
|
||||
try_cb(c->n, s, r->n);
|
||||
if (try_cb(c->n, s, r->n)) [[unlikely]] return true;
|
||||
for (auto const j : r->rightwards()) {
|
||||
j->c->CoverCol();
|
||||
}
|
||||
self(self);
|
||||
undo_cb();
|
||||
if (self(self)) [[unlikely]] return true;
|
||||
if (undo_cb()) [[unlikely]] return true;
|
||||
for (auto const j : r->leftwards()) {
|
||||
j->c->UncoverCol();
|
||||
}
|
||||
}
|
||||
c->UncoverCol();
|
||||
return false;
|
||||
};
|
||||
recurse(recurse);
|
||||
}
|
||||
|
Reference in New Issue
Block a user