knights_tour.cpp 8.0 KB

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