-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgridbfs.h
130 lines (113 loc) · 2.69 KB
/
gridbfs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef GRIDBFS_H_
#define GRIDBFS_H_
#include "grid.h"
#include <queue>
#include <iterator>
template <typename Passable>
class GridBfs : std::iterator<std::forward_iterator_tag, Location>
{
public:
GridBfs()
: dist(-1)
{ }
GridBfs(const Location &start, const Passable &p = Passable())
: dist(0)
, passable(p)
{
visited.reset();
q.push(start);
visited(start) = TDIRECTIONS + 1; // "don't move"
q.push(Location(-1, -1));
enqueueAll();
}
GridBfs(const GridBfs &other)
: dist(other.dist)
, passable(other.passable)
, q(other.q)
, visited(other.visited)
{ }
const Location & operator * () const
{
return q.front();
}
const Location * operator -> () const
{
return &(operator*());
}
GridBfs & operator ++ ()
{
q.pop();
while (q.front().row == -1) {
dist++;
q.pop();
if (!q.empty())
q.push(Location(-1, -1));
}
if (q.empty())
dist = -1;
else
enqueueAll();
return *this;
}
GridBfs operator ++ (int)
{
GridBfs tmp = *this;
++*this;
return tmp;
}
bool operator == (const GridBfs &rhs) const
{
// XXX poor condition
return dist == rhs.dist && (dist == -1 || q == rhs.q);
}
bool operator != (const GridBfs &rhs) const
{
return !(*this == rhs);
}
int distance() const
{
return dist;
}
int direction() const
{
return visited(q.front()) - 1;
}
int direction2() const
{
int d = direction();
Location next = state.getLocation(q.front(), d);
int d2 = visited(next) - 1;
if (d2 != -1 && d2 != TDIRECTIONS) {
next = state.getLocation(q.front(), d2);
int d3 = visited(next) - 1;
if (d3 != -1 && d3 != TDIRECTIONS) {
if (BEHIND[d3] != d2)
return d2;
}
}
return d;
}
protected:
void enqueue(int dr, int dc, int dir)
{
int r = state._row(q.front().row + dr);
int c = state._col(q.front().col + dc);
const Location loc(r, c);
if (!visited(loc) && passable(loc)) {
q.push(loc);
visited(loc) = dir + 1;
}
}
void enqueueAll()
{
enqueue(-1, 0, 2); // go back S
enqueue(0, 1, 3); // go back W
enqueue(1, 0, 0); // go back N
enqueue(0, -1, 1); // go back E
}
int dist;
Passable passable;
std::queue<Location> q;
Grid<char> visited;
};
#endif /* GRIDBFS_H_ */