链接
小红正在玩一个游戏。游戏的地图是一个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<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<algorithm>
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");
}