• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=======================================================================
2 // Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee,
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
8 #include <boost/config.hpp>
9 #include <stdlib.h>
10 #include <iostream>
11 #include <stack>
12 #include <queue>
13 #include <ctime>
14 #include <boost/operators.hpp>
15 #include <boost/graph/breadth_first_search.hpp>
16 #include <boost/graph/visitors.hpp>
17 #include <boost/property_map/property_map.hpp>
18 
19 using namespace boost;
20 
21 typedef std::pair< int, int > Position;
22 Position knight_jumps[8]
23     = { Position(2, -1), Position(1, -2), Position(-1, -2), Position(-2, -1),
24           Position(-2, 1), Position(-1, 2), Position(1, 2), Position(2, 1) };
25 
operator +(const Position & p1,const Position & p2)26 Position operator+(const Position& p1, const Position& p2)
27 {
28     return Position(p1.first + p2.first, p1.second + p2.second);
29 }
30 
31 struct knights_tour_graph;
32 struct knight_adjacency_iterator
33 : public boost::forward_iterator_helper< knight_adjacency_iterator, Position,
34       std::ptrdiff_t, Position*, Position >
35 {
knight_adjacency_iteratorknight_adjacency_iterator36     knight_adjacency_iterator() {}
knight_adjacency_iteratorknight_adjacency_iterator37     knight_adjacency_iterator(int ii, Position p, const knights_tour_graph& g)
38     : m_pos(p), m_g(&g), m_i(ii)
39     {
40         valid_position();
41     }
operator *knight_adjacency_iterator42     Position operator*() const { return m_pos + knight_jumps[m_i]; }
operator ++knight_adjacency_iterator43     void operator++()
44     {
45         ++m_i;
46         valid_position();
47     }
operator ==knight_adjacency_iterator48     bool operator==(const knight_adjacency_iterator& x) const
49     {
50         return m_i == x.m_i;
51     }
52 
53 protected:
54     void valid_position();
55     Position m_pos;
56     const knights_tour_graph* m_g;
57     int m_i;
58 };
59 
60 struct knights_tour_graph
61 {
62     typedef Position vertex_descriptor;
63     typedef std::pair< vertex_descriptor, vertex_descriptor > edge_descriptor;
64     typedef knight_adjacency_iterator adjacency_iterator;
65     typedef void out_edge_iterator;
66     typedef void in_edge_iterator;
67     typedef void edge_iterator;
68     typedef void vertex_iterator;
69     typedef int degree_size_type;
70     typedef int vertices_size_type;
71     typedef int edges_size_type;
72     typedef directed_tag directed_category;
73     typedef disallow_parallel_edge_tag edge_parallel_category;
74     typedef adjacency_graph_tag traversal_category;
knights_tour_graphknights_tour_graph75     knights_tour_graph(int n) : m_board_size(n) {}
76     int m_board_size;
77 };
num_vertices(const knights_tour_graph & g)78 int num_vertices(const knights_tour_graph& g)
79 {
80     return g.m_board_size * g.m_board_size;
81 }
82 
valid_position()83 void knight_adjacency_iterator::valid_position()
84 {
85     Position new_pos = m_pos + knight_jumps[m_i];
86     while (m_i < 8
87         && (new_pos.first < 0 || new_pos.second < 0
88             || new_pos.first >= m_g->m_board_size
89             || new_pos.second >= m_g->m_board_size))
90     {
91         ++m_i;
92         new_pos = m_pos + knight_jumps[m_i];
93     }
94 }
95 
96 std::pair< knights_tour_graph::adjacency_iterator,
97     knights_tour_graph::adjacency_iterator >
adjacent_vertices(knights_tour_graph::vertex_descriptor v,const knights_tour_graph & g)98 adjacent_vertices(
99     knights_tour_graph::vertex_descriptor v, const knights_tour_graph& g)
100 {
101     typedef knights_tour_graph::adjacency_iterator Iter;
102     return std::make_pair(Iter(0, v, g), Iter(8, v, g));
103 }
104 
105 struct compare_first
106 {
operator ()compare_first107     template < typename P > bool operator()(const P& x, const P& y)
108     {
109         return x.first < y.first;
110     }
111 };
112 
113 template < typename Graph, typename TimePropertyMap >
backtracking_search(Graph & g,typename graph_traits<Graph>::vertex_descriptor src,TimePropertyMap time_map)114 bool backtracking_search(Graph& g,
115     typename graph_traits< Graph >::vertex_descriptor src,
116     TimePropertyMap time_map)
117 {
118     typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
119     typedef std::pair< int, Vertex > P;
120     std::stack< P > S;
121     int time_stamp = 0;
122 
123     S.push(std::make_pair(time_stamp, src));
124     while (!S.empty())
125     {
126         Vertex x;
127         boost::tie(time_stamp, x) = S.top();
128         put(time_map, x, time_stamp);
129         // all vertices have been visited, success!
130         if (time_stamp == num_vertices(g) - 1)
131             return true;
132 
133         bool deadend = true;
134         typename graph_traits< Graph >::adjacency_iterator i, end;
135         for (boost::tie(i, end) = adjacent_vertices(x, g); i != end; ++i)
136             if (get(time_map, *i) == -1)
137             {
138                 S.push(std::make_pair(time_stamp + 1, *i));
139                 deadend = false;
140             }
141 
142         if (deadend)
143         {
144             put(time_map, x, -1);
145             S.pop();
146             boost::tie(time_stamp, x) = S.top();
147             while (get(time_map, x) != -1)
148             { // unwind stack to last unexplored vertex
149                 put(time_map, x, -1);
150                 S.pop();
151                 boost::tie(time_stamp, x) = S.top();
152             }
153         }
154 
155     } // while (!S.empty())
156     return false;
157 }
158 
159 template < typename Vertex, typename Graph, typename TimePropertyMap >
number_of_successors(Vertex x,Graph & g,TimePropertyMap time_map)160 int number_of_successors(Vertex x, Graph& g, TimePropertyMap time_map)
161 {
162     int s_x = 0;
163     typename graph_traits< Graph >::adjacency_iterator i, end;
164     for (boost::tie(i, end) = adjacent_vertices(x, g); i != end; ++i)
165         if (get(time_map, *i) == -1)
166             ++s_x;
167     return s_x;
168 }
169 
170 template < typename Graph, typename TimePropertyMap >
warnsdorff(Graph & g,typename graph_traits<Graph>::vertex_descriptor src,TimePropertyMap time_map)171 bool warnsdorff(Graph& g, typename graph_traits< Graph >::vertex_descriptor src,
172     TimePropertyMap time_map)
173 {
174     typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
175     typedef std::pair< int, Vertex > P;
176     std::stack< P > S;
177     int time_stamp = 0;
178 
179     S.push(std::make_pair(time_stamp, src));
180     while (!S.empty())
181     {
182         Vertex x;
183         boost::tie(time_stamp, x) = S.top();
184         put(time_map, x, time_stamp);
185         // all vertices have been visited, success!
186         if (time_stamp == num_vertices(g) - 1)
187             return true;
188 
189         // Put adjacent vertices into a local priority queue
190         std::priority_queue< P, std::vector< P >, compare_first > Q;
191         typename graph_traits< Graph >::adjacency_iterator i, end;
192         int num_succ;
193         for (boost::tie(i, end) = adjacent_vertices(x, g); i != end; ++i)
194             if (get(time_map, *i) == -1)
195             {
196                 num_succ = number_of_successors(*i, g, time_map);
197                 Q.push(std::make_pair(num_succ, *i));
198             }
199         bool deadend = Q.empty();
200         // move vertices from local priority queue to the stack
201         for (; !Q.empty(); Q.pop())
202         {
203             boost::tie(num_succ, x) = Q.top();
204             S.push(std::make_pair(time_stamp + 1, x));
205         }
206         if (deadend)
207         {
208             put(time_map, x, -1);
209             S.pop();
210             boost::tie(time_stamp, x) = S.top();
211             while (get(time_map, x) != -1)
212             { // unwind stack to last unexplored vertex
213                 put(time_map, x, -1);
214                 S.pop();
215                 boost::tie(time_stamp, x) = S.top();
216             }
217         }
218 
219     } // while (!S.empty())
220     return false;
221 }
222 
223 struct board_map
224 {
225     typedef int value_type;
226     typedef Position key_type;
227     typedef read_write_property_map_tag category;
board_mapboard_map228     board_map(int* b, int n) : m_board(b), m_size(n) {}
229     friend int get(const board_map& ba, Position p);
230     friend void put(const board_map& ba, Position p, int v);
231     friend std::ostream& operator<<(std::ostream& os, const board_map& ba);
232 
233 private:
234     int* m_board;
235     int m_size;
236 };
237 
get(const board_map & ba,Position p)238 int get(const board_map& ba, Position p)
239 {
240     return ba.m_board[p.first * ba.m_size + p.second];
241 }
242 
put(const board_map & ba,Position p,int v)243 void put(const board_map& ba, Position p, int v)
244 {
245     ba.m_board[p.first * ba.m_size + p.second] = v;
246 }
247 
operator <<(std::ostream & os,const board_map & ba)248 std::ostream& operator<<(std::ostream& os, const board_map& ba)
249 {
250     for (int i = 0; i < ba.m_size; ++i)
251     {
252         for (int j = 0; j < ba.m_size; ++j)
253             os << get(ba, Position(i, j)) << "\t";
254         os << std::endl;
255     }
256     return os;
257 }
258 
main(int argc,char * argv[])259 int main(int argc, char* argv[])
260 {
261     int N;
262     if (argc == 2)
263         N = atoi(argv[1]);
264     else
265         N = 8;
266 
267     knights_tour_graph g(N);
268     int* board = new int[num_vertices(g)];
269     board_map chessboard(board, N);
270     for (int i = 0; i < N; ++i)
271         for (int j = 0; j < N; ++j)
272             put(chessboard, Position(i, j), -1);
273 
274     bool ret = warnsdorff(g, Position(0, 0), chessboard);
275 
276     if (ret)
277         for (int i = 0; i < N; ++i)
278         {
279             for (int j = 0; j < N; ++j)
280                 std::cout << get(chessboard, Position(i, j)) << "\t";
281             std::cout << std::endl;
282         }
283     else
284         std::cout << "method failed" << std::endl;
285     return 0;
286 }
287