dancing_links.hppGo to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef ADOBE_DANCING_LINKS_HPP
00010 #define ADOBE_DANCING_LINKS_HPP
00011
00012
00013
00014 #include <adobe/config.hpp>
00015
00016 #include <boost/function.hpp>
00017 #include <boost/noncopyable.hpp>
00018 #include <adobe/implementation/toroid.hpp>
00019
00020
00021
00022 namespace adobe {
00023
00024
00025
00026 #ifndef ADOBE_NO_DOCUMENTATION
00027
00028
00029
00030 namespace implementation {
00031
00032
00033
00034 struct do_nothing_callback_t
00035 {
00036 inline void operator () (std::size_t, bool) const
00037 { }
00038 };
00039
00040
00041
00042 struct select_right_heuristic_t
00043 {
00044 template <std::size_t Rows, std::size_t Cols, std::size_t NodeBlockSize>
00045 inline toroid_header_t* operator () (binary_toroid<Rows, Cols, NodeBlockSize>& toroid) const
00046 { return toroid.right_of(&toroid.header_m); }
00047 };
00048
00049
00050
00051 struct select_most_constrained_heuristic_t
00052 {
00053 template <std::size_t Rows, std::size_t Cols, std::size_t NodeBlockSize>
00054 inline toroid_header_t* operator () (binary_toroid<Rows, Cols, NodeBlockSize>& toroid) const
00055 {
00056 toroid_header_t* c(toroid.right_of(&toroid.header_m));
00057 std::size_t sz(c->size_m);
00058
00059 for ( toroid_header_t* p(toroid.right_of(c));
00060 p != &toroid.header_m; p = toroid.right_of(p))
00061 {
00062 if (p->size_m < sz)
00063 {
00064 c = p;
00065 sz = p->size_m;
00066 }
00067
00068 if (sz == 1) break;
00069 }
00070
00071 return c;
00072 }
00073 };
00074
00075
00076
00077 }
00078
00079
00080
00081 #endif
00082
00083
00084
00085 template <std::size_t Rows, std::size_t Cols>
00086 class dancing_links : boost::noncopyable
00087 {
00088 public:
00089 #ifndef ADOBE_NO_DOCUMENTATION
00090 dancing_links() :
00091 solutions_m(0)
00092 { }
00093 #endif
00094
00095 inline void set(std::size_t row, std::size_t col)
00096 { toroid_m.set(row, col); }
00097
00098 inline void set_secondary_column(std::size_t col)
00099 { toroid_m.set_secondary_column(col); }
00100
00101 template <typename ResultCallback>
00102 inline std::size_t search(std::size_t max_solutions, ResultCallback callback)
00103 {
00104 max_solutions_m = max_solutions;
00105
00106 toroid_m.finalize();
00107
00108 #if 1
00109 do_search(0, callback, implementation::select_most_constrained_heuristic_t());
00110 #else
00111 do_search(0, callback, implementation::select_right_heuristic_t());
00112 #endif
00113
00114 return solutions_m;
00115 }
00116
00117 inline std::size_t search(std::size_t max_solutions)
00118 { return search(max_solutions, implementation::do_nothing_callback_t()); }
00119
00120 private:
00121 template <typename ResultCallback, typename SearchHeuristic>
00122 void do_search(std::size_t k, ResultCallback callback, SearchHeuristic heuristic)
00123 {
00124 if (toroid_m.right_of(&toroid_m.header_m) == &toroid_m.header_m)
00125 {
00126 ++solutions_m;
00127
00128 for (std::size_t i(0); i < k; ++i)
00129 callback(toroid_m.row_index_of(output_m[i]), i + 1 == k);
00130
00131 return;
00132 }
00133
00134 std::size_t next_k(k + 1);
00135
00136 toroid_header_t* c(heuristic(toroid_m));
00137
00138 toroid_m.cover_column(c);
00139
00140 for (toroid_node_t* r(toroid_m.down_of(c));
00141 r != c; r = toroid_m.down_of(r))
00142 {
00143 output_m[k] = r;
00144
00145 for (toroid_node_t* j1(toroid_m.right_of(r));
00146 j1 != r; j1 = toroid_m.right_of(j1))
00147 { toroid_m.cover_column(toroid_m.column_of(j1)); }
00148
00149 do_search(next_k, callback, heuristic);
00150
00151 if (solutions_m >= max_solutions_m) return;
00152
00153 r = output_m[k];
00154
00155 c = toroid_m.column_of(r);
00156
00157 for (toroid_node_t* j(toroid_m.left_of(r));
00158 j != r; j = toroid_m.left_of(j))
00159 { toroid_m.uncover_column(toroid_m.column_of(j)); }
00160 }
00161
00162 toroid_m.uncover_column(c);
00163 };
00164
00165 binary_toroid<Rows, Cols> toroid_m;
00166 toroid_node_t* output_m[Cols];
00167 std::size_t solutions_m;
00168 std::size_t max_solutions_m;
00169 };
00170
00171
00172
00173 }
00174
00175
00176
00177 #endif
00178
00179
|