题目链接: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;
}
既然看到底了,如果有一点点帮助,何不点个赞再走呢!!!