回家
题目描述
小 H 在一个划分成了 n × m n \times m n×m 个方格的长方形封锁线上。 每次他能向上下左右四个方向移动一格(当然小 H 不可以静止不动), 但不能离开封锁线,否则就被打死了。 刚开始时他有满血 6 6 6 点,每移动一格他要消耗 1 1 1 点血量。一旦小 H 的血量降到 0 0 0, 他将死去。 他可以沿路通过拾取鼠标(什么鬼。。。)来补满血量。只要他走到有鼠标的格子,他不需要任何时间即可拾取。格子上的鼠标可以瞬间补满,所以每次经过这个格子都有鼠标。就算到了某个有鼠标的格子才死去, 他也不能通过拾取鼠标补满 HP。 即使在家门口死去, 他也不能算完成任务回到家中。
地图上有五种格子:
0:障碍物。
1:空地, 小 H 可以自由行走。
2:小 H 出发点, 也是一片空地。
3:小 H 的家。
4:有鼠标在上面的空地。
小 H 能否安全回家?如果能, 最短需要多长时间呢?
输入格式
第一行两个整数 n , m n,m n,m, 表示地图的大小为 n × m n \times m n×m。
下面 n n n 行, 每行 m m m 个数字来描述地图。
输出格式
一行, 若小 H 不能回家, 输出 -1,否则输出他回家所需最短时间。
样例 #1
样例输入 #1
3 3
2 1 1
1 1 0
1 1 3
样例输出 #1
4
提示
对于所有数据, 1 ≤ n , m ≤ 9 1 \le n,m \le 9 1≤n,m≤9。
#include<iostream>
#include<algorithm>
#include <cstring>
#include<queue>
using namespace std;
#define N 10
typedef struct Place{
int x;
int y;
int step;
int HP; //可能多次走到这个地方,血量不一样
}Place;//存放坐标,步数,血量,
queue<Place> q;
int g[N][N];//图的信息
int d[N][N];//最大血量信息
int n, m;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
int bfs()
{
memset(d, 0, sizeof d);//初始化为0表示血量为0
while(q.size())
{
Place t = q.front();
q.pop();
if(g[t.x][t.y] == 3)
return t.step;//代表已经扩展走到家了
if(t.HP > 1)//hp<= 1都表示死了,下一步都会死
{
for(int i = 0; i < 4; i++)
{
int x = t.x + dx[i];
int y = t.y + dy[i];
if(x >= 0 && x < n && y >= 0 && y < m )
{
if(g[x][y] == 1 || g[x][y] == 3)//能往下一步走
if(d[x][y] < t.HP - 1)//并且如果这次血量比最大血量大
{
d[x][y] = t.HP - 1;//更新最大血量
q.push(Place{x, y, t.step + 1, d[x][y]});//扩展
}
if(g[x][y] == 4)//只能走一次带鼠标的位置
if(!d[x][y])
{
d[x][y] = 1;
q.push(Place{x, y, t.step + 1, 6});
}
}
}
}
}
return -1;//没找到路径
}
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
{
cin >> g[i][j];
if(g[i][j] == 2)
{
q.push(Place{i, j, 0, 6});//找入口
d[i][j] = 1;//已走过
}
}
cout << bfs();
return 0;
}
291

被折叠的 条评论
为什么被折叠?



