题意就是给出一个地图。有一个起点,一个终点
我们要从起点到终点去。但是地上有毒液,不能走,不过有一些箱子可以供你跳来跳去。这些箱子的高度是2,3或者4
然后每次跳一步只能去4个方向相邻坐标的箱子。箱子之间不用管高度是多少,只要相邻了就可以跳上去
而且箱子可以放倒。也是4个方向,放倒后的长度就是之前的高度,但是放倒一次后就不能再放倒了。我们可以规定此时的高度为1。而且放倒必须是有确切的那么多空位才能放倒,如果前边有箱子挡着或者前面是终点挡着了,都不能放倒
然后问最少多少步能到终点,放倒箱子和跳箱子都算1步
这题我刚开始用了个很奇葩的5进制去表示每行的状态来节省空间,结果没判状态的重复,悲惨的TLE了
因为在BFS的过程中是能改变地图的,所以判状态是否以前出现过就比较麻烦,不过还算好写。
把整张地图作为一个字符串hash了,塞到一个表里,然后每次扩展状态的时候从表里看是否出现过,就可以了
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define MAXN 100005
#define MAXM 200005
#define INF 1000000011
#define lch(x) x<<1
#define rch(x) x<<1|1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define eps 1e-7
using namespace std;
int mod = 100003;
unsigned int Hash(char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;
while (*str) hash = hash * seed + (*str++);
return (hash & 0x7FFFFFFF) % mod;
}
struct P
{
int x, y, num, next;
char s[70];
P(){}
P(int _x, int _y, int _num, char *_s){x = _x; y = _y; num = _num; strcpy(s, _s);}
}edge[MAXM * 2], q[MAXM + 5];
int head[MAXN], e;
int n, sx, sy, ex, ey;
char tmp[70];
char mp[70];
int xx[] = {1, 0, -1, 0};
int yy[] = {0, 1, 0, -1};
void init()
{
memset(head, -1, sizeof(head));
e = 0;
}
void add(int u, int x, int y, char *s)
{
edge[e].x = x;
edge[e].y = y;
strcpy(edge[e].s, s);
edge[e].next = head[u];
head[u] = e++;
}
bool ok(int x, int y, char *s)
{
if(x < 0 || y < 0 || x >= n || y >= n || s[x * n + y] == '.') return 0;
int u = Hash(s);
for(int i = head[u]; i != -1; i = edge[i].next)
{
if(edge[i].x == x && edge[i].y == y && strcmp(s, edge[i].s) == 0) return 0;
}
return 1;
}
void bfs()
{
int h = 0, t = 0;
if(ok(sx, sy, mp))
{
q[t++] = P(sx, sy, 0, mp);
add(Hash(mp), sx, sy, mp);
}
int ans = -1;
while(h != t)
{
P tp = q[h++];
if(h >= MAXM) h -= MAXM;
if(tp.x == ex && tp.y == ey)
{
ans = tp.num;
break;
}
for(int i = 0; i < 4; i++)
{
int tx = tp.x + xx[i];
int ty = tp.y + yy[i];
if(ok(tx, ty, tp.s))
{
q[t++] = P(tx, ty, tp.num + 1, tp.s);
if(t >= MAXM) t -= MAXM;
add(Hash(tp.s), tx, ty, tp.s);
}
}
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < n * n; j++) tmp[j] = tp.s[j];
tmp[n * n] = '\n';
int k = tmp[tp.x * n + tp.y] - '0';
if(k == 1) continue;
int tx = tp.x, ty = tp.y;
int flag = 0;
for(int j = 0; j < k; j++)
{
tx += xx[i];
ty += yy[i];
if(tx < 0 || ty < 0 || tx >= n || ty >= n || tmp[tx * n + ty] != '.') flag = 1;
}
if(flag) continue;
tx = tp.x, ty = tp.y;
tmp[tx * n + ty] = '.';
for(int j = 0; j < k; j++)
{
tx += xx[i];
ty += yy[i];
tmp[tx * n + ty] = '1';
}
tx = tp.x + xx[i], ty = tp.y + yy[i];
if(ok(tx, ty, tmp))
{
q[t++] = P(tx, ty, tp.num + 1, tmp);
if(t >= MAXM) t -= MAXM;
add(Hash(tmp), tx, ty, tmp);
}
}
}
if(ans == -1) printf("Impossible.\n");
else printf("%d\n", ans);
}
int main()
{
while(scanf("%d%d%d", &n, &sx, &sy) != EOF)
{
if(!n && !sx && !sy) break;
sx--;
sy--;
init();
for(int i = 0; i < n; i++)
{
scanf("%s", tmp);
for(int j = 0; j < n; j++)
{
mp[i * n + j] = tmp[j];
if(tmp[j] == 'E') mp[i * n + j] = '1', ex = i, ey = j;
}
}
mp[n * n] = '\0';
bfs();
}
return 0;
}