leetcode 6054. 逃离火灾 思维 bfs

15 篇文章 1 订阅
7 篇文章 1 订阅

link

思路:
当然可以二分 + bfs 复杂度 O ( l o g ( n ∗ m ) n ∗ m ) O(log(n*m)n*m) O(log(nm)nm) 这个比较好想,但如何进一步优化,我们可以逆向考虑,从终点倒着找到离终点最近的火和最近的人的距离,当然如果火比人先到那肯定就是-1,如果找不到火就是1e9,然后就判断最近的火和人的位置关系,因为右下角只有两种转移位置,一种是上方一种是左方,有个比较有意思的性质,到两个方向的人的差要么是0,要么是1,而火的差距可以取到0,1,2,大家可以思考一下为什么?
如果最近的火到这两个位置都是最小值,那么人肯定要提早走一次,答案要减1,如果人到上侧和左侧是最小值,那么人可以选择一个地方走避免和火走同一个位置不用减1,如果上两种情况都不是,那么判断火和人是否走唯一方向就可以了,如果是同个方向就减1。复杂度 O ( 3 ∗ n ∗ m ) O(3*n*m) O(3nm)

int dist[310][310];
int maxv[310][310];
int st[310][310];
class Solution {
public:
    int maximumMinutes(vector<vector<int>>& grid) {
        int n=grid.size();
        int m=grid[0].size();
        queue<pair<int,int>>qq;
        int dx[]={0,0,1,-1};
        int dy[]={1,-1,0,0};
        auto solve = [&](int ex,int ey)
        {
            int fire=0x3f3f3f3f;
            int human=0x3f3f3f3f;
            queue<pair<int,int>>q;
            if(grid[ex][ey]==2)    return -1;
            q.push({ex,ey});
            memset(st,-1,sizeof st);
            st[ex][ey]=0;
            while(q.size())
            {
                auto tt=q.front();
                q.pop();
                if(fire==0x3f3f3f3f && grid[tt.first][tt.second]==1)
                    fire=st[tt.first][tt.second];
                if(human==0x3f3f3f3f && tt.first==0 && tt.second==0)
                    human=st[tt.first][tt.second];
                for(int i=0;i<4;i++)
                {
                    int tx=tt.first+dx[i];
                    int ty=tt.second+dy[i];
                    if(tx>=n || ty>=m || tx<0 || ty<0 || grid[tx][ty]==2 || st[tx][ty]!=-1)  continue;
                    st[tx][ty]=st[tt.first][tt.second]+1;
                    q.push({tx,ty});
                }
            }
            if(human==0x3f3f3f3f)   return -1;
            if(fire==0x3f3f3f3f)    return (int)1e9;
            return fire-human;
        };
        int xx=solve(n-1,m-1);
        if(xx==-1)  return -1;
        if(xx==1e9) return 1e9;
        int a=solve(n-2,m-1);
        int b=solve(n-1,m-2);
        if(max(a,b)==xx)    xx--;
        if(xx<0)    xx=-1;
        return xx;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值