// http://okajima.air-nifty.com/b/2010/01/post-abc6.html
// 2010-1-12 10:56 http://twitter.com/koizuka
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <map>
struct coord {
int x;
int y;
coord(int _x = 0, int _y = 0)
:x(_x), y(_y) {}
};
bool operator < ( const coord& a, const coord& b )
{
if ( a.y != b.y ) {
return a.y < b.y;
}
return a.x < b.x;
}
coord operator +( const coord& a, const coord& b )
{
return coord( a.x + b.x, a.y + b.y );
}
bool operator ==( const coord& a, const coord& b )
{
return a.x == b.x && a.y == b.y;
}
int main() {
std::vector<std::string> input_lines;
size_t width = 0;
// read the maze
while ( !std::cin.eof() ) {
std::string line;
// MAX LINE WIDTH
char linebuf[4096];
std::cin.getline(linebuf, sizeof linebuf, '\n');
size_t len = strlen(linebuf);
line.append( linebuf, len );
// stop when empty line occurs
if ( line.size() == 0 ) {
break;
}
input_lines.push_back(line);
width = std::max( width, line.size() );
}
size_t height = input_lines.size();
typedef std::map<coord, int> dist_map_type;
dist_map_type dist_map;
coord start, goal;
// parse the maze
for ( unsigned y = 0 ; y < height ; ++y ) {
for ( unsigned x = 0 ; x < width ; ++x ) {
coord c(x,y);
switch ( input_lines[y][x] ) {
case 'S':
start = c;
break;
case 'G':
goal = c;
break;
case '*':
dist_map[c] = -1;
break;
}
}
}
const coord directions[4] = { coord(1,0), coord(0,1), coord(-1,0), coord(0,-1) };
const size_t num_directions = (sizeof directions) / (sizeof directions[0]);
// fill distances
{
std::deque<coord> next_queue;
next_queue.push_back( start );
dist_map[start] = 0;
while ( !next_queue.empty() ) {
coord c = next_queue.front();
if ( c == goal ) {
break; // stop when c has reached the goal
}
int dist = dist_map[c] + 1;
next_queue.pop_front();
for ( int d = 0 ; d < num_directions ; ++d ) {
coord n = c + directions[d];
if ( n.x < 0 || n.x >= width || n.y < 0 || n.y >= height ) {
continue;
}
dist_map_type::const_iterator i = dist_map.find(n);
if ( i != dist_map.end() ) {
if ( i->second <= dist ) {
continue;
}
}
dist_map[n] = dist;
next_queue.push_back(n);
}
}
}
// draw a path
std::map<coord, bool> path_map;
{
coord c = goal;
int dist = dist_map[c];
while ( dist > 0 ) {
path_map[c] = true;
for ( int d = 0 ; d < num_directions ; ++d ) {
coord n = c + directions[d];
dist_map_type::const_iterator i = dist_map.find(n);
if ( i == dist_map.end() ) {
continue;
}
int n_dist = i->second;
if ( n_dist == dist - 1 ) {
c = n;
break;
}
}
--dist;
}
}
// show the result
std::cout << "result:" << std::endl;
for ( unsigned y = 0 ; y < height ; ++y ) {
for ( unsigned x = 0 ; x < width ; ++x ) {
char c = input_lines[y][x];
if ( c == ' ' && path_map[coord(x,y)] ) {
c = '$';
}
std::cout.put(c);
}
std::cout << std::endl;
}
return 0;
}
// vim: noet sw=4 ts=4 fdm=marker cindent aw cino=\:0g0i0
syntax highlighted by Code2HTML, v. 0.9.1