【洛谷P2802】回家

搜索play的第三弹!

回家

题目描述

小 H 在一个划分成了 \(n \times m\) 个方格的长方形封锁线上。 每次他能向上下左右四个方向移动一格(当然小 H 不可以静止不动), 但不能离开封锁线,否则就被打死了。 刚开始时他有满血 \(6\) 点,每移动一格他要消耗 \(1\) 点血量。一旦小 H 的血量降到 \(0\), 他将死去。 他可以沿路通过拾取鼠标(什么鬼。。。)来补满血量。只要他走到有鼠标的格子,他不需要任何时间即可拾取。格子上的鼠标可以瞬间补满,所以每次经过这个格子都有鼠标。就算到了某个有鼠标的格子才死去, 他也不能通过拾取鼠标补满 HP。 即使在家门口死去, 他也不能算完成任务回到家中。

地图上有五种格子:

0:障碍物。

1:空地, 小 H 可以自由行走。

2:小 H 出发点, 也是一片空地。

3:小 H 的家。

4:有鼠标在上面的空地。

小 H 能否安全回家?如果能, 最短需要多长时间呢?

输入格式

第一行两个整数 \(n,m\), 表示地图的大小为 \(n \times m\)

下面 \(n\) 行, 每行 \(m\) 个数字来描述地图。

输出格式

一行, 若小 H 不能回家, 输出 -1,否则输出他回家所需最短时间。

样例 #1

样例输入 #1

3 3
2 1 1
1 1 0
1 1 3

样例输出 #1

4

提示

对于所有数据,\(1 \le n,m \le 9\)

2021.9.2 增添一组 hack 数据 by @囧仙

解法&个人感想

这题不可能是橙题啊喂!我调的都想不做了!
而且题解还打不开!
列举一下这题的坑点吧
首先:卡DFS DFS的point 1必定TLE
然后:因为可能反复经过某个鼠标格子从而回满血,所以vis不止是0和1
那应该是什么呢?想了很久发现 因为vis和step是独立的 vis只针对能不能到这回事
然后ans只要到了才更新(所以得先满足到了吧!)
因此 vis应该记录到当前格子的最大生命(如果小于就回溯 不然怎么到得了嘛)
下面看代码吧!

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m;
int ma[11][11];
int vis[11][11];
int dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
int sx,sy,fx,fy;
const int INF=1e9;
int ans=INF;//ans赋大值来看它是否变化
struct node{
    int x,y,t,b;
};
void bfs(){
    queue<node>q;
    q.push(node{sx,sy,0,6});
    vis[sx][sy]=6;.//这个别忘了
    while(!q.empty()){
        int ax=q.front().x,ay=q.front().y;
        int ab=q.front().b,at=q.front().t;
        if(ab==0||at>=ans||at>=n*m){
            q.pop();
            continue;
        }
        if(ma[ax][ay]==4){
            ab=6;
        }
        if(ax==fx&&ay==fy){
            ans=min(ans,at);
            q.pop();
            continue;
        }
        for(int i=1;i<=4;i++){
            int tx=ax+dx[i],ty=ay+dy[i];
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&ab-1>vis[tx][ty]&&ma[tx][ty]!=0){
                vis[tx][ty]=ab-1;
                q.push(node{tx,ty,at+1,ab-1});
            }
        }
        q.pop();
    }//我们重点看这里的回溯位置 就是直接出队然后continue 从而正常出队应该放后面(以前没见过)
    return ;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&ma[i][j]);
            if(ma[i][j]==2){
                ma[i][j]=1;
                sx=i,sy=j;
            }
            if(ma[i][j]==3){
                ma[i][j]=1;
                fx=i,fy=j;
            }
        }
    }
    bfs();
    if(ans==INF){
        cout<<-1;
    }
    else cout<<ans;
    system("pause");
    return 0;
}

  

posted @ 2025-02-01 18:58  Elainafan  阅读(5)  评论(0编辑  收藏  举报