牛客小bai月赛41 小红的rpg游戏(广搜 三维数组)

链接
小红正在玩一个游戏。游戏的地图是一个nm的迷宫,迷宫有墙和道路,道路上可能会有一些怪物。
小红初始的血量是 h ,每当小红经过一个有怪物的道路时,小红就会和怪物战斗,击杀怪物并且消耗自己的血量。小红消耗的血量等同于该怪物的战斗力。请注意,如果小红血量为0则死亡。因此只有当小红当前血量大于怪物的战斗力时才可经过该点。
地图共有以下几种标识:
‘.’ 代表道路,小红可以经过。
'
’ 代表墙体,小红不能经过。
‘1’~‘9’ 数字,代表该位置是个道路,且上面有一个战斗力为该数字的怪物。
小红只可以上下左右四个方向移动。
小红想知道,自己从左上角到右下角的最短行走路线的距离是多少?
输入描述:
第一行三个正整数 n 、m 和 h ,用空格隔开。
接下来的 nn 行,每行一个长度为 m 的字符串,用来表示地图。保证输入是合法的。
数据范围:
2\leq n,m,h \leq 502≤n,m,h≤50,且怪物的数量不超过10个。保证左上角和右下角都是道路且没有怪物。
输出描述:
如果小红无法到达右下角,则输出-1。否则输出一个正整数,代表小红走的路径长度最小值。
示例1
输入
复制
3 3 3
.11
..
22.
输出
复制
4
说明
小红先向右走两步,再向下走两步,可到达右下角。中途击杀两只战斗力为1的怪物,剩余血量为1。若小红先向下走,则无法击杀两只血量为2的怪物,无法到达终点。
示例2
输入
复制
3 3 3
.12
.
.
21.
输出
复制
-1
分析:基础迷宫问题,必须要把走过的点标记一下,除了标记点外还要标记走到这个点的血量,因为第一次走到一个点它的血量不一定是最多的,有可能还有其他情况走到这个点血量和步数都是最优的!
AC代码:

#include
#include
#include
#include
#include
using namespace std;
char a[100][100];
int vis[55][55][51];
int n,m,h,flag;
int ne[4][2]={0,1,0,-1,1,0,-1,0};
struct node
{
	int x,y,h,st;
}head,tail;
int check(int x,int y)
{
	if(x<0||y<0||x>=n||y>=m||a[x][y]=='*')
	return 1;
	return 0;
}
int dfs()
{
	queue<node> q;
	head.x=0;
	head.y=0;
	head.h=h;
	head.st=0;
	vis[head.x][head.y][head.h]=1;
	q.push(head);
	while(!q.empty())
	{
		head=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			tail.x=head.x+ne[i][0];
			tail.y=head.y+ne[i][1];
			tail.st=head.st+1;
			if(tail.x==n-1&&tail.y==m-1)
			{
				printf("%d\n",tail.st);
				flag=1;
				return flag;
			}	
			if(a[tail.x][tail.y]>='1'&&a[tail.x][tail.y]<='9')
			tail.h=head.h-(a[tail.x][tail.y]-'0');
			else tail.h=head.h;
			if(tail.h<=0)
			continue;	
			if(check(tail.x,tail.y)||vis[tail.x][tail.y][tail.h])
			continue;
			vis[tail.x][tail.y][tail.h]=1;
			q.push(tail);
		}
	}
	return flag;	
}
int main()
{
	int i;
	scanf("%d%d%d",&n,&m,&h);
	for(i=0;i<n;i++)
	scanf("%s",a[i]);
	dfs();
	if(flag==0)
	printf("-1\n");
}

你可能感兴趣的:(深搜广搜,数据结构)