1215. 脱离地牢
解题技巧:1.广度优先搜索
2.分离地图和人物位置状态
3.压缩人物位置状态为一个整数,以便去掉重复的状态
#include <cstdio>
#include <set>
#include <map>
#include <queue>
using namespace std;
struct Cor {
int r, c;
Cor(int r_ = 0, int c_ = 0) : r(r_), c(c_) {}
Cor operator+(const Cor &cor) {
return Cor(r + cor.r, c + cor.c);
}
Cor& operator=(const Cor &cor) {
r = cor.r;
c = cor.c;
return *this;
}
bool operator==(const Cor&cor) {
return r == cor.r && c == cor.c;
}
};
struct State {
Cor h, p;
State() {}
};
struct Map {
static const int maxr = 20;
static const int maxc = 20;
static const int maxd = 4;
static const int HR = 1;
static const int HC = 100;
static const int PR = 10000;
static const int PC = 1000000;
static const int max_step = 255;
char m[maxr][maxc+1];
char p_d[maxd + 1];
char h_d[maxd + 1];
int rows, cols;
queue<State> state_queue;
map<char, Cor> d_x;
set<int> ids;
bool success;
int step;
void init() {
d_x.insert(make_pair('N', Cor(-1, 0)));
d_x.insert(make_pair('S', Cor(1, 0)));
d_x.insert(make_pair('W', Cor(0, -1)));
d_x.insert(make_pair('E', Cor(0, 1)));
p_d[0] = 'N'; p_d[1] = 'S'; p_d[2] = 'W'; p_d[3] = 'E';
while (!state_queue.empty()) state_queue.pop();
}
void input() {
scanf("%d%d", &rows, &cols);
for (int r = 0; r < rows; ++r)
scanf("%s", m[r]);
scanf("%s", h_d);
}
int makeId(const State & state) {
return state.h.r * HR + state.h.c * HC + state.p.r * PR + state.p.c * PC;
}
void extractHP() {
State state;
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
if (m[r][c] == 'H') {
state.h.r = r;
state.h.c = c;
m[r][c] = '.';
} else if (m[r][c] == 'P') {
state.p.r = r;
state.p.c = c;
m[r][c] = '.';
}
}
}
int id = makeId(state);
ids.insert(id);
state_queue.push(state);
}
void solve() {
success = false;
step = 0;
while (!state_queue.empty() && step < max_step && !success) {
++step;
int size = state_queue.size();
while (size-- && !success) {
State &state = state_queue.front();
for (int i = 0; i < maxd; ++i) {
Cor & p_d_cor = d_x[p_d[i]];
Cor & h_d_cor = d_x[h_d[i]];
State next_state;
next_state.h = state.h + h_d_cor;
if (m[next_state.h.r][next_state.h.c] == '#') {
next_state.h = state.h;
} else if (m[next_state.h.r][next_state.h.c] == '!') {
continue;
}
next_state.p = state.p + p_d_cor;
if (m[next_state.p.r][next_state.p.c] == '#') {
continue;
} else if (m[next_state.p.r][next_state.p.c] == '!') {
continue;
}
if ((next_state.h == next_state.p) || (next_state.h == state.p && next_state.p == state.h)) {
// 达到目的地
success = true;
break;
}
int id = makeId(next_state);
if (ids.find(id) == ids.end()) {
ids.insert(id);
state_queue.push(next_state);
}
}
state_queue.pop();
}
}
}
};
int main() {
Map mp;
mp.init();
mp.input();
mp.extractHP();
mp.solve();
if (mp.success) {
printf("%d\n", mp.step);
} else {
printf("%s\n", "Impossible");
}
return 0;
}
浙公网安备 33010602011771号