Skip to content

Instantly share code, notes, and snippets.

@macrat
Created June 3, 2016 16:59
Show Gist options
  • Save macrat/57bc92ec6314f259ea505c46fa7c5859 to your computer and use it in GitHub Desktop.
Save macrat/57bc92ec6314f259ea505c46fa7c5859 to your computer and use it in GitHub Desktop.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <set>
#include <vector>
class Position {
private:
int x, y;
public:
Position(int x, int y) : x(x), y(y) { }
Position(const Position& m) : x(m.x), y(m.y) { }
Position() : x(0), y(0) { }
Position operator +(const Position p) const {
return Position(x + p.x, y + p.y);
}
Position operator =(const Position& p) {
x = p.x;
y = p.y;
return *this;
}
int getX() const {
return x;
}
int getY() const {
return y;
}
bool operator ==(const Position& p) const {
return x == p.x && y == p.y;
}
bool operator !=(const Position& p) const {
return !(*this == p);
}
bool operator <(const Position& p) const {
return x < p.x || y < p.y;
}
};
class Map {
private:
std::vector< std::vector<bool> > data;
public:
const int w, h, level;
Position start, goal;
private:
std::pair<Position, bool> find(const Position shift) const {
if(!is_valid(start + shift) || !get(start + shift)){
return {start, false};
}
Position cur(start);
while(is_valid(cur + shift) && get(cur + shift) && cur != goal){
cur = cur + shift;
}
return {cur, true};
}
public:
Map(const int w, const int h) : w(w), h(h), level(1) {
for(int x=0; x<w; x++){
data.push_back(std::vector<bool>(h));
}
}
Map(const Map& m) : w(m.w), h(m.h), level(m.level + 1), start(m.start), goal(m.goal) {
std::copy(m.data.begin(), m.data.end(), std::back_inserter(data));
}
static Map* read(const int w, const int h) {
Map* map = new Map(w, h);
for(int y=0; y<h; y++){
for(int x=0; x<w; x++){
int t;
std::cin >> t;
switch(t){
case 2:
map->start = Position(x, y);
break;
case 3:
map->goal = Position(x, y);
break;
}
map->set(Position(x, y), t!=1);
}
}
return map;
}
bool is_valid(const Position pos) const {
return 0 <= pos.getX() && pos.getX() < w && 0 <= pos.getY() && pos.getY() < h;
}
bool get(const Position pos) const {
return is_valid(pos) && data[pos.getX()][pos.getY()];
}
void set(const Position pos, bool value) {
if(is_valid(pos)){
data[pos.getX()][pos.getY()] = value;
}
}
template <class T> int search(T& stack) const {
if(level > 10){
return -1;
}
const Position shifts[] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};
for(int i=0; i<4; i++){
const auto result = find(shifts[i]);
if(result.first == goal){
return level;
}
if(result.second){
Map* next = new Map(*this);
next->start = result.first;
next->set(result.first + shifts[i], true);
stack.insert(next);
}
}
return -1;
}
};
struct map_compare {
bool operator() (const Map* x, const Map* y) const {
if(x->level != y->level)
return x->level < y->level;
return x->start < y->start;
}
};
int main() {
while(true){
int w, h;
std::cin >> w >> h;
if(w == 0)
break;
std::set<Map*, map_compare> maps;
maps.insert(Map::read(w, h));
int r;
for(auto itr=maps.begin(); itr!=maps.end(); ++itr){
if((r = (*itr)->search(maps)) > 0){
break;
}
}
std::cout << r << std::endl;
for(auto itr=maps.begin(); !maps.empty();){
delete *itr;
itr = maps.erase(itr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment