洛谷P2802 回家

回家

题目描述

小 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 1n,m9

#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;
} 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值