【NOI】6044 鸣人和佐助

7 篇文章 0 订阅

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

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

输入
输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
输出
输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出-1。

-

BFS板子
不知道为啥很玄学的W了又很玄学的A了:D

#include<cstdio>
#include<cstring>
using namespace std;

int n,m,x1,y1,
    X[5]={ 0, 1, 0,-1},
Y[5]={ 1, 0,-1, 0};
    //右 下 左 上 
int a[403][403],
    kl[403][403];

int main()
{
int x[100010],y[100010],//坐标 
    t[100010],//时间 
k[100010],//查克拉 
    f[100010],//方向 
h,l;

h=l=1;f[1]=4;//一开始没有方向 
scanf("%d%d%d",&n,&m,&k[h]);
//我就n行m列你能咋滴:D 
for(int i=1;i<=n;++i)
{
    char c; scanf("%c",&c);//吃空格 
for(int j=1;j<=m;++j)
{
    scanf("%c",&c);
    switch(c)
{
    case '#':a[i][j]=1;break;//手下 
    case '@':x[1]=i;y[1]=j;break;//起点 
    case '+':x1=i;y1=j;break;//终点 
        }
}
}


memset(kl,-1,sizeof(kl));//防止下面查克拉没了后判断出错 
kl[x[1]][y[1]]==k[h];
do
{
for(int i=0;i<4;++i)//循环方向 
  if(f[h]!=(i+2)%4)//不和之前的方向相反 
  {
    int xx=x[h]+X[i],
        yy=y[h]+Y[i];//移动后的坐标 
    if(xx>=1&&xx<=n&&yy>=1&&yy<=m)//在地图里 
      if(k[h]-a[xx][yy]>=0)//能打过手下 
        if(k[h]-a[xx][yy]>kl[xx][yy])//查克拉比以前要多 
        //加了这句就A了??? 
        {
      if(xx==x1&&yy==y1)//追到了 
      {printf("%d",t[h]+1);return 0;}
      ++l;//继续追 
      f[l]=i;//方向记录
      x[l]=xx;y[l]=yy;//存坐标 
      t[l]=t[h]+1;//+1s 
      k[l]=k[h]-a[xx][yy];//查克拉
      kl[xx][yy]=k[l];
        }
  }
++h;
}
while(h<=l);
printf("-1");
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值