题目
描述
在一场DOTA战争中,影魔终于获得获得了传说中的闪烁匕首,也就用了闪烁技能,但是闪烁有个缺陷——我们把地图看做N*N的点阵,假设影魔在点(x,y)上,那么闪烁只能让他到达(x±2,y±2)的四个点,前提是这个点存在并且上面没有石头或者树这种障碍。可恶的是,敌方的英雄早已在地图上布下了减速陷阱,如果踩中陷阱,将会让他减速,但陷阱也会消失!现在影魔要从敌人的包围中逃脱,即从左上顶点(1,1)逃到右下顶点(N,N),请你帮他算出逃脱所需的最短时间!
注:闪烁一次花费1s,踩中陷阱停滞1s,当然,影魔也可以选择向上下左右四个方向移动1个单位,每次移动花费1s。
输入
第一行包含一个数N(2<=N<=50)
接下来的N行表示N*N的地图。其中0表示空地,1表示障碍,2表示陷阱,保证(1,1)和(N,N)为0
输出
输出逃脱花费的最短时间
如果无法逃脱,输出”Impossible”
输入样例
4
0000
0000
0000
0000
输出样例
3
思路分析
BFS,区别在于陷阱需要+1。
【我的代码】
#include <queue>
#include <cstring>
typedef struct pos {
int x, y, cnt;
}pos;
int directions[8][2] = {{2, 2}, {2, -2}, {-2, 2}, {2, -2}, {1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n;
queue<pos> maze;
char map_char;
int map[51][51] = {0};
int visited[51][51] = {0};
int cnt[51][51] = {0};
int min_step = 999999;
int bfs()
{
int step = 1;
while (maze.size())
{
pos top_item = maze.front();
maze.pop();
if (map[top_item.x][top_item.y] == 1 || top_item.x < 1 || top_item.x > n || top_item.y < 1 || top_item.y > n || (visited[top_item.x][top_item.y] == 1 && top_item.cnt >= cnt[top_item.x][top_item.y]))
continue;
cnt[top_item.x][top_item.y] = top_item.cnt;
int tcnt = top_item.cnt + 1;
if (map[top_item.x][top_item.y] == 2) {
tcnt++;
}
for (int i = 0; i < 8; i++)
{
pos new_item = {directions[i][0] + top_item.x, directions[i][1] + top_item.y, tcnt};
maze.push(new_item);
}
visited[top_item.x][top_item.y] = 1;
step++;
}
}
int main(){
cin >> n;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cin >> map_char;
map[i][j] = int(map_char) - 48;
}
}
pos begin = {1, 1, 0};
maze.push(begin);
bfs();
if (cnt[n][n])
cout << cnt[n][n] << endl;
else
cout << "Impossible" << endl;
return 0;
}