Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/graph/example/knights-tour.cpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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