还是见的题太少了。
思路跟杭电1253基本一样的,就是多了一个权值会改变的点。
用个三维数组来记录每层走过的路径(这是一直卡我的地方,没写过这种姿势)。
这种思想相当于复制了几份原图,每一个编号的钥匙对应一层图, 这样就可以确保同一层不能走重复点,不同层可以走上一层走过的点。
在状态中保存一下已经杀死蛇的编号,防止同一路径中二次杀死同一条蛇。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <map>
#include <iostream>
using namespace std;
const int move[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct State
{
int x, y, dist, key;
int snake[6];
State(int _x, int _y, int d, int k): x(_x), y(_y), dist(d), key(k){}
State(){}
bool operator < (const State &a)const
{
return dist > a.dist;//优先队列搜最小距离的点,保证最短路
}
};
struct Point//每条蛇的位置
{
int x, y;
Point(int _x, int _y): x(_x), y(_y){}
Point(){}
}snake[6];
char mapp[110][110];
int vis[110][110][11];
priority_queue<State> que;
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) && (n + m))
{
if(n + m == 0) break;
for(int i = 0; i < n; i++)
scanf("%s", mapp[i]);
int sx, sy, ex, ey;
int tt = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(mapp[i][j] == 'K')
sx = i, sy = j;
else if(mapp[i][j] == 'T')
ex = i, ey = j;
else if(mapp[i][j] == 'S')
{
snake[tt].x = i;
snake[tt].y = j;
tt++;
}
}
while(!que.empty()) que.pop();
State tmp(sx, sy, 0, 0);
for(int i = 0; i < tt; i++)
tmp.snake[i] = 0;
memset(vis, 0, sizeof(vis));
que.push(tmp);
vis[sx][sy][0] = 1;
while(!que.empty())
{
tmp = que.top();
if(tmp.x == ex && tmp.y == ey && tmp.key == m)
{
printf("%d\n", tmp.dist);
break;
}
que.pop();
for(int i = 0; i < 4; i++)
{
int nx = tmp.x + move[i][0];
int ny = tmp.y + move[i][1];
if(
nx >= 0 && ny >= 0 &&
nx < n && ny < n &&
vis[nx][ny][tmp.key] == 0 &&
mapp[nx][ny] != '#')
{
State cur;
for(int i = 0; i < tt; i++)
cur.snake[i] = tmp.snake[i];
cur.x = nx;
cur.y = ny;
cur.key = tmp.key;
cur.dist = tmp.dist + 1;
if(mapp[nx][ny] == 'S')
{
int i;
for(i = 0; i < tt; ++i)
{
if(snake[i].x == nx && snake[i].y == ny)
break;
}
if(cur.snake[i] == 0) //如果这条蛇没有在这条路径上,那么杀死它
{
cur.snake[i] = 1;
cur.dist += 1;
}
}
else if(mapp[nx][ny] <= '9' && mapp[nx][ny] >= '0')
{
if(mapp[nx][ny] -'0' == tmp.key + 1)//是需要的钥匙,取它
{
cur.key += 1;
}
}
que.push(cur);
vis[nx][ny][cur.key] = 1;//标记该钥匙对点的图走过
}
}
}
if(que.empty())
{
printf("impossible\n");
}
}
return 0;
}