计蒜客--T1214--鸣人和佐助--bfs+三维数组标记

题目链接:https://nanti.jisuanke.com/t/T1214

题目描述:

佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?

已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费 11 个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?

输入格式:

输入的第一行包含三个整数:MM,NN,TT。代表 MM 行 NN 列的地图和鸣人初始的查克拉数量 TT。0 < M,N < 2000<M,N<200,0 \le T < 100≤T<10

后面是 MM 行 NN 列的地图,其中 @ 代表鸣人,+ 代表佐助。* 代表通路,# 代表大蛇丸的手下。

输出格式:

输出包含一个整数 RR,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出 -1−1。

输出时每行末尾的多余空格,不影响答案正确性

样例输入1

4 4 1
#@##
**##
###+
****

样例输出1

6

样例输入2

4 4 2
#@##
**##
###+
****

样例输出2

4

 解题思路:

1.这道题在搜索的过程中并不能只单纯的记录到达某个点的最短路,因为显然到达 (x,y) 时如果查克拉分别剩余 a,b 这两种是不同的状态,有可能导致不同的结果,但是你只会判断第一次到达 (x,y) 的状态,所以用二维数组标记并不能解决问题。

优先队列+二维数组标记也解决不了问题。

2.这题用三维数组来标记某个点是否走过,(i,j,k)分别代表横坐标,纵坐标和查克拉

3.这题还是用数组来代替队列写的。

 代码:

#include<iostream>
using namespace std;
int book[201][201][15]={0};//标记数组 
struct dd
{
	int x;
	int y;
	int c;//查克拉数量 
	int time;//时间 
}a[400001]; 
int main()
{
	int i,j,n,m,t,tx,ty;
	char s[201][201]; 
	int next[4][2]={0,1,1,0,0,-1,-1,0};
	int head=1,tail=1,flag=0;
	cin>>n>>m>>t;
	for(i=0;i<n;i++)
	{
		for(j=0;j<m;j++)
		{
			cin>>s[i][j];
			if(s[i][j]=='@')
			{
				tx=i;
				ty=j;
			}
		}
	}
	a[tail].x=tx;
	a[tail].y=ty;
	a[tail].c=t;
	a[tail].time=0;
	book[tx][ty][a[tail].c]=1;
	tail++;
	while(head<tail)
	{
		for(i=0;i<4;i++)
		{
			tx=a[head].x+next[i][0];
			ty=a[head].y+next[i][1];
			if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty][a[head].c]==1)
				continue;	   
			if(s[tx][ty]=='#'&&a[head].c>0)//大蛇丸手下 
			{
				book[tx][ty][a[head].c-1]=1;
				a[tail].x=tx;
				a[tail].y=ty;
				a[tail].c=a[head].c-1;//查克拉减少1 
				a[tail].time=a[head].time+1; 
				tail++;
			}
			if(s[tx][ty]=='*'||s[tx][ty]=='+')//通路或者佐助
			{
				book[tx][ty][a[head].c]=1;
				a[tail].x=tx;
				a[tail].y=ty;
				a[tail].c=a[head].c;//查克拉不变 
				a[tail].time=a[head].time+1; 
				tail++;
			}
			if(s[tx][ty]=='+') 
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
			break;
		head++;
	}
	if(flag==1)
		cout<<a[tail-1].time<<endl;
	else
		cout<<-1<<endl;
	return 0; 
}

既然看到底了,如果有一点点帮助,何不点个赞再走呢!!!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值