OpenJ_Bailian - 4115 鸣人和佐助(bfs+三维标记)

4115:鸣人和佐助

总时间限制: 

1000ms

 

内存限制: 

65536kB

描述

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

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

输入

输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。

输出

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

样例输入

样例输入1
4 4 1
#@##
**##
###+
****

样例输入2
4 4 2
#@##
**##
###+
****

样例输出

样例输出1
6

样例输出2
4

刚开始用普通的bfs做的,(二维数组,二维标记),不知道为啥一直wa;

后来听学长讲了题;QAQ;一个经典的错误样例;

3   6    1

@#**** 
*#*###
***##+

正确答案应该是11;

但是二维标记答案是-1;因为二位标记是bfs找最短路,当(1,1)——>(2,1)——>(3,1)——>(3,2)——>

(3,3)——>(2,3)——>(1,3),当这样找到(1,3)时,(1,3)早已经被(1,1)——>(1,2)——>(1,3)

走过并标记了,所以这条不需要查克拉的路就走不下去了,输出-1;

用三维数组就可以避免这种情况;

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <list>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

int n,m,t,sx,sy,ex,ey;
char s[210][210];
int v[210][210][10] = {0};//重点:用三维数组标记

struct id{
    int x,y,s,t;//x,y是位置,s是走到这一点的步数,t是这一点拥有的查克拉的数量
    id(){}
    id(int a,int b,int k,int r){
      x=a,y=b,s=k,t=r;
    }
}ids[210];

int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};

int dfs(){
    int nx,ny,i;
    queue<id>q;
    q.push(id(sx,sy,0,t));
    v[sx][sy][t] = 1;

    while(!q.empty()){
        id k = q.front();
        q.pop();
        for(i = 0;i < 4;i++){
            nx=k.x+dx[i],ny=k.y+dy[i];
            if(nx<0||nx>=n||ny<0||ny>=m||v[nx][ny][k.t]) continue;
            if(s[nx][ny] == '+'){
                return k.s+1;//到达终点
            }
            if(s[nx][ny] == '#' && k.t>0){
                    v[nx][ny][k.t] = 1;
                q.push(id(nx,ny,k.s+1,k.t-1));//需要一个查克拉打败大蛇丸手下
            }
            if(s[nx][ny] == '*'){
                v[nx][ny][k.t] = 1;
                q.push(id(nx,ny,k.s+1,k.t));//通路
            }
        }
    }
    return (-1);
}
int main()
{
    cin >> n>>m>>t;
    int i,j;
    for(i = 0;i < n;i++)
        for(j = 0;j < m;j++){
            cin>>s[i][j];
            if(s[i][j] == '@') sx=i,sy=j;//起点
            if(s[i][j] == '+') ex=i,ey=j;//终点
        }
    cout<<dfs()<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42754600/article/details/81461152