LeetCode 675. Cut Off Trees for Golf Event(宽搜)

题目链接

https://leetcode.com/problems/cut-off-trees-for-golf-event/

题意

给出一个 n * m 的地图,其中有包括树和障碍。从(0,0)开始出发,在避开障碍的情况下,需要按照树的高度从矮到高依次到达,问一共最少需要多少步。无法依次达到,则输出 -1。

思路

  1. 先对地图中的树的高度进行排序,得到总的路径。
  2. 对于路径中的每一个节点,将问题转变为从 A 点到 B 点的最短路程的子问题。
  3. 对每个子问题进行宽度搜索,将所有子问题的最短路程相加即可。当某个子问题无解时,则直接输出 -1

代码

// 宽搜,参数:Map,A.x,A.y,B.x,B.y
var calStep = function(forest, x1, y1, x2, y2) {
    let vis = [];   // 用来记录该位置是否访问过,避免重复递归
    let h = forest.length;
    let w = forest[0].length
    for (let i = 0; i < h; i++) {
        let tmp = [];
        for (let j = 0; j < w; j++) {
            tmp.push(0);
        }
        vis.push(tmp);
    }
    vis[x1][y1] = 1;
    let q = [];
    q.push({x: x1, y: y1, step: 0});
    while(q.length > 0) {
        let item = q.shift();
        // 若已到达 B 点,返回步数
        if (item.x === x2 && item.y === y2) {
            return item.step;
        }
        // 对当前节点,若其上下左右节点合法,且未访问,则放入队列中待判
        if (item.x-1 >= 0 && !vis[item.x - 1][item.y] && forest[item.x - 1][item.y]) {
            vis[item.x - 1][item.y] = 1;
            q.push({x: item.x - 1, y: item.y, step: item.step + 1});
        }
        if (item.x+1 < h && !vis[item.x + 1][item.y] && forest[item.x + 1][item.y]) {
            vis[item.x + 1][item.y] = 1;
            q.push({x: item.x + 1, y: item.y, step: item.step + 1});
        }
        if (item.y-1 >= 0 && !vis[item.x][item.y - 1] && forest[item.x][item.y - 1]) {
            vis[item.x][item.y - 1] = 1;
            q.push({x: item.x, y: item.y - 1, step: item.step + 1});
        }
        if (item.y+1 < w && !vis[item.x][item.y + 1] && forest[item.x][item.y + 1]) {
            vis[item.x][item.y + 1] = 1;
            q.push({x: item.x, y: item.y + 1, step: item.step + 1});
        }
    }
    return -1;
}
    
/**
 * @param {number[][]} forest
 * @return {number}
 */
var cutOffTree = function(forest) {
    let tree = [];
    for (let i = 0; i < forest.length; i++) {
        for (let j = 0; j < forest[i].length; j++) {
            if (forest[i][j] !== 0) {
                tree.push({val: forest[i][j], x: i, y: j});
            }
        }
    }
    // 对树的高度进行排序
    tree.sort((a, b) => {
        if (a.val < b.val) {
            return -1;
        }
        return 1;
    })
    let result = 0;
    for (let i = 0; i < tree.length; i++) {
        if (i === 0) {
            let step = calStep(forest, 0, 0, tree[i].x, tree[i].y);
            if (step === -1) {
                return -1;
            }
            result = result + step;
        } else {
            let step = calStep(forest, tree[i - 1].x, tree[i - 1].y, tree[i].x, tree[i].y);
            if (step === -1) {
                return -1;
            }
            result = result + step;
        }
    }
    return result;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值