题目见:http://code.google.com/codejam/contest/32003/dashboard#s=p1
思路:
根据迷宫的行走路径倒推迷宫的结构。首先确定保存迷宫的数据结构。用普通的数组是不合适的,因为不知道迷宫的大小,也不知道迷宫入口的坐标。好在题目已经给定入口处在北方,所以迷宫只可能向三个方向延展。南北方向只要能够实现向容器后插入元素即可,东西方向需要能够方便的在容器前后都插入。同时还需要方便的按索引访问。这样比较合适的容器就只有std::deque了。每移动到一个新的坐标,就按照移动方向标记前一个坐标的出口和当前坐标的入口。最后再输出整个迷宫的信息。
题解:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <deque>
#include <unordered_map>
using namespace std;
class Maze
{
enum
{
NORTH = (1<<0),
SOUTH = (1<<1),
WEST = (1<<2),
EAST = (1<<3)
};
const string SPOT_STATUS = "0123456789abcdef";
const unordered_map<int, int> TurnRight {{
{NORTH, EAST},
{SOUTH, WEST},
{EAST, SOUTH},
{WEST, NORTH}
}
};
const unordered_map<int, int> TurnLeft {{
{NORTH, WEST},
{SOUTH, EAST},
{EAST, NORTH},
{WEST, SOUTH}
}
};
const unordered_map<int, int> FlipMove {{
{NORTH, SOUTH},
{SOUTH, NORTH},
{EAST, WEST},
{WEST, EAST}
}
};
const unordered_map<int, pair<int, int>> MoveForward {{
{NORTH, {-1, 0}},
{SOUTH, {1, 0}},
{WEST, {0, -1}},
{EAST, {0, 1}}
}
};
int CurrentDirection;
int MaxR, MaxC;
int CurR, CurC;
deque<deque<int>> Grid;
void MoveAndExtend()
{
if (CurR < 0)
{
// this should not happen
// since we always enter the maze at north side
// neglect this section
}
else if (CurR >= MaxR)
{
++MaxR;
Grid.emplace_back (deque<int> (MaxC, 0));
}
else if (CurC < 0)
{
++CurC;
++MaxC;
for (auto& r : Grid)
r.push_front (0);
CurC = 0;
}
else if (CurC >= MaxC)
{
++MaxC;
for (auto& r : Grid)
r.push_back (0);
}
Grid[CurR][CurC] |= FlipMove.at (CurrentDirection);
}
void Visit (const string& v)
{
for (auto& ch : v)
{
switch (ch)
{
case 'W':
Grid[CurR][CurC] |= CurrentDirection;
CurR += MoveForward.at (CurrentDirection).first;
CurC += MoveForward.at (CurrentDirection).second;
MoveAndExtend();
break;
case 'R':
CurrentDirection = TurnRight.at (CurrentDirection);
break;
case 'L':
CurrentDirection = TurnLeft.at (CurrentDirection);
break;
}
}
}
public:
void BidirectionTraverse (const string& forward, const string& backward)
{
MaxR = MaxC = 1;
CurC = 0;
CurR = 0; // we enter from outside of the maze
Grid.push_back (deque<int> (1, 0));
CurrentDirection = SOUTH;
// Give the entrance "CAN WALK NORTH" attribute
Grid[0][0] |= NORTH;
// we neglect the first move-in and last move-out instruction
Visit (forward.substr (1, forward.size()-2));
Grid[CurR][CurC] |= CurrentDirection;
CurrentDirection = FlipMove.at (CurrentDirection);
Visit (backward.substr (1, backward.size()-2));
}
void Print()
{
for (auto& c1 : Grid)
{
for (auto& c2 : c1)
cout<<SPOT_STATUS[c2];
cout<<endl;
}
}
};
int main (int argc, char* argv[])
{
int num_sample;
cin>>num_sample;
vector<Maze> m;
for (int i = 0; i < num_sample; ++i)
{
string enter, exit;
cin>>enter>>exit;
m.push_back (Maze());
m.back().BidirectionTraverse (enter, exit);
}
for (int i = 0; i < num_sample; ++i)
{
cout<<"Case #"<<i+1<<":"<<endl;
m[i].Print();
}
return 0;
}