This commit is contained in:
2022-11-20 10:09:23 -08:00
parent eac45695b5
commit 50640e6adb
2 changed files with 122 additions and 102 deletions

View File

@@ -7,7 +7,7 @@
namespace dlx {
class Dlx {
class Dlx final {
struct Cell {
Cell *U, *D, *L, *R;
@@ -17,42 +17,18 @@ class Dlx {
std::size_t s;
};
auto LR_self() -> void { L = R = this; }
auto UD_self() -> void { U = D = this; }
auto LR_delete() -> void { L->R = R; R->L = L; }
auto UD_delete() -> void { U->D = D; D->U = U; }
auto UD_restore() -> void { U->D = D->U = this; }
auto LR_restore() -> void { L->R = R->L = this; }
auto LR_insert(Cell* k) -> void { L = k->L; R = k; k->L = k->L->R = this; }
auto UD_insert(Cell* k) -> void { U = k->U, D = k, k->U = k->U->D = this; }
static Cell* ColNew() {
auto c = new Cell;
c->UD_self();
c->s = 0;
return c;
}
auto CoverCol() -> void {
LR_delete();
for (auto i = D; i != this; i = i->D) {
for (auto j = i->R; j != i; j = j->R) {
j->UD_delete();
j->c->s--;
}
}
}
auto UncoverCol() -> void {
for (auto i = U; i != this; i = i->U) {
for (auto j = i->L; j != i; j = j->L) {
j->c->s++;
j->UD_restore();
}
}
LR_restore();
}
auto LR_self() -> void;
auto UD_self() -> void;
auto LR_delete() -> void;
auto UD_delete() -> void;
auto UD_restore() -> void;
auto LR_restore() -> void;
auto LR_insert(Cell* k) -> void;
auto UD_insert(Cell* k) -> void;
auto CoverCol() -> void;
auto UncoverCol() -> void;
auto ColAdd(std::size_t row_id) -> Cell*;
static Cell* ColNew();
};
std::vector<Cell*> ctab_;
@@ -68,6 +44,12 @@ public:
Dlx();
~Dlx();
Dlx(Dlx const&) = delete;
auto operator=(Dlx const&) -> Dlx& = delete;
Dlx(Dlx &&);
auto operator=(Dlx &&) -> Dlx&;
// Returns number of rows.
auto Rows() const -> std::size_t;
@@ -82,14 +64,14 @@ public:
// but it still must respect the constraints it entails.
auto MarkOptional(std::size_t col) -> void;
// Removes a row from consideration. Returns 0 on success, -1 otherwise.
// Removes a row from consideration.
// Should only be called after all dlx_set() calls.
auto RemoveRow(std::size_t row) -> int;
auto RemoveRow(std::size_t row) -> void;
// Picks a row to be part of the solution. Returns 0 on success, -1 otherwise.
// Should only be called after all dlx_set() calls and dlx_remove_row() calls.
// Picks a row to be part of the solution.
// Should only be called after all Set() calls and RemoveRows() calls.
// TODO: Check the row can be legally chosen.
auto PickRow(std::size_t row) -> int;
auto PickRow(std::size_t row) -> void;
auto Solve(
std::function<void(std::size_t, std::size_t, std::size_t)> try_cb,