这题从昨天做到今天,各种错误。以前做过类似的题,是用状态压缩保存当前拥有钥匙的状态,看到这题毫不犹豫的写了。开标记数组的时候,因为钥匙最多有9把,1<<9再加上地图和蛇,发现开不下这么大。就各种剪支,然后又发现这题因为有蛇的存在,bfs第一次得到的答案并不是最优解,还得跑完整个队列才行,各种问题,一直GG。然后发现这题的钥匙必须按照顺序来拿,所以用不着状态压缩。把杀死蛇的状态压缩后,只用开1<<5 开的下,于是开4维标记数组的bfs就可以写了。(中间不想跑完整个队列,所以重载结构体后用优先队列,这样也不行)
存图时预先把图中的蛇处理成1-5的数字,这些技巧看了别人的,学到了学到了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
const int inf = 1<<20;
const int maxn = 105;
char g[maxn][maxn];
int d[maxn][maxn][10][33];
int n, m, sn;
int sx, sy;
struct node{
int x, y, k, s, d;
node(int xx, int yy, int kk, int ss, int dd):x(xx),y(yy),k(kk),s(ss),d(dd) {
}
};
void init() {
sn = 0;
memset(g, 0, sizeof(g));
memset(d, -1, sizeof(d));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%c", &g[i][j]);
if (g[i][j] == 'S') {
g[i][j] = 'A' + sn;
sn++;
}
if (g[i][j] == 'K') {
sx = i;
sy = j;
}
}
getchar();
}
}
void bfs(int x, int y, int key, int snum) {
queue<node> q;
while (!q.empty())
q.pop();
int ans = inf;
node start(x, y, key, snum, 0);
q.push(start);
while (!q.empty()) {
node tmp = q.front();
q.pop();
x = tmp.x;
y = tmp.y;
key = tmp.k;
snum = tmp.s;
if (key == m && g[x][y] == 'T')
{ ans = min(ans, tmp.d); continue;}
if (d[x][y][key][snum] != -1)
continue;
d[x][y][key][snum] = tmp.d;
for (int i = 0; i < 4; i++) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
int st = g[tx][ty] - 'A';
if (st >= 0 && st < sn) {
if (snum & (1 << st))
q.push(node(tx, ty, key, snum, tmp.d + 1));
else
q.push(node(tx, ty, key, (snum | (1 << st)), tmp.d + 2));
}
else if (g[tx][ty] == '1' + key)
q.push(node(tx, ty, key + 1, snum, tmp.d + 1));
else if (g[tx][ty] >= '1' && g[tx][ty] < '1' + m)
q.push(node(tx, ty, key, snum, tmp.d + 1));
else if (g[tx][ty] == '.' || g[tx][ty] == 'K' || g[tx][ty] == 'T')
q.push(node(tx, ty, key, snum, tmp.d + 1));
}
}
if(ans!=inf) printf("%d\n",ans);
else printf("impossible\n");
}
int main() {
while (scanf("%d %d", &n, &m) && (n || m)) {
getchar();
init();
bfs(sx, sy, 0, 0);
}
return 0;
}
好题,因为太菜,所以超耐磨!