leetcode(为高尔夫比赛砍树)

本文探讨了在大规模格点地图中寻找最短路径的问题,指出Floyd和Dijkstra算法在某些情况下效率不高。作者推荐使用A*算法,并详细解释了其实现过程,包括关键的启发式函数和开放/关闭列表的管理。A*算法在保持效率的同时,能有效处理复杂场景,如无人驾驶和导航中的路径规划。
摘要由CSDN通过智能技术生成

求两点之间最短路径,个人平常用的最多的是floyd算法,算法相当简洁,写起来也方便,但是这里的格点比较多,不适合floyd,而对于dijkstra算法,当树接节点占满图后,直接退化成floyd算法,时间复杂度也变得不是很理想,这里用A* (求路径有各种各样的算法,有A*的变种,也有些对于实时度较高的甚至采用蚁群算法,这是个很复杂的领域,无人驾驶,导航,路由,加速器,都用到路径规划,但针对某一特定问题选择的算法都会不同。):

var cutOffTree = function(forest) {
    var ans = 0;
    //floyd
    var trees = [];
    for(let i = 0; i < forest.length; i++) {
        for(let j = 0; j < forest[i].length; j++) {
            if(forest[i][j] > 1) {
                trees.push([forest[i][j],[i,j]]);
            }
        }
    }
    trees.sort((a, b)=>{
        return a[0] - b[0];
    });
    trees.unshift([1,[0,0]]);
    
    //A*,floyd(时间复杂度是最高的),dijkstra(居中),bfs(时间复杂度过高)
    //2500个树节点会退化到O(n^3)
    //采用A*
    const A_STAR = (sourceX, sourceY, targetX, targetY) => {
        let CLOSED = [];
        let OPEN = [];
        let MAP_CLOSED = [];
        let MAP_OPEN = [];
        const calc_h = (curX,curY, targetX, targetY) => {
            return Math.abs(curX - targetX) + Math.abs(curY - targetY);
        }
        OPEN.push([0,[sourceX, sourceY, 0]]);
        MAP_OPEN[sourceX] = MAP_OPEN[sourceX] ? MAP_OPEN[sourceX] : [];
        MAP_OPEN[sourceX][sourceY] = 1;
        while(true) {
            if(OPEN.length == 0) {
                return -1;
            } else {
                let prepare_pos = 0;
                for(let i = 1; i < OPEN.length; i++) {
                    if(OPEN[i][0] == OPEN[prepare_pos][0]) {
                        if(OPEN[i][1][0] == targetX && OPEN[i][1][1] == targetY) {
                            prepare_pos = i;break;
                        }
                    } else {
                        break;
                    }
                }
                let cur_node = JSON.parse(JSON.stringify(OPEN.splice(prepare_pos, 1)[0]));
                CLOSED.push(JSON.parse(JSON.stringify(cur_node)));
                cur_node = cur_node[1];
                MAP_CLOSED[cur_node[0]] = MAP_CLOSED[cur_node[0]] ? MAP_CLOSED[cur_node[0]] : [];
                MAP_CLOSED[cur_node[0]][cur_node[1]] = 1;
                MAP_OPEN[cur_node[0]][cur_node[1]] = 0;
                if(cur_node[0] == targetX && cur_node[1] == targetY) {
                    //console.log(cur_node);
                    return cur_node[2];
                }
                let son_node = [];
                if(cur_node[0] - 1 >= 0 && forest[cur_node[0] - 1][cur_node[1]] > 0) {
                    son_node.push([cur_node[0] - 1, cur_node[1]]);
                }
                if(cur_node[0] + 1 < forest.length && forest[cur_node[0] + 1][cur_node[1]] > 0) {
                    son_node.push([cur_node[0] + 1, cur_node[1]]);
                }
                if(cur_node[1] - 1 >= 0 && forest[cur_node[0]][cur_node[1]-1] > 0) {
                    son_node.push([cur_node[0], cur_node[1]-1]);
                }
                if(cur_node[1] + 1 < forest[0].length && forest[cur_node[0]][cur_node[1]+1] > 0) {
                    son_node.push([cur_node[0], cur_node[1]+1]);
                }
                for(let i = 0; i < son_node.length; i++) {
                    let h = cur_node[2] + 1 + calc_h(son_node[i][0],son_node[i][1],targetX,targetY);
                    if(
                        (MAP_CLOSED[son_node[i][0]] == undefined || MAP_CLOSED[son_node[i][0]][son_node[i][1]] == undefined || !MAP_CLOSED[son_node[i][0]][son_node[i][1]]) 
                        &&
                        (MAP_OPEN[son_node[i][0]] == undefined || MAP_OPEN[son_node[i][0]][son_node[i][1]] == undefined || !MAP_OPEN[son_node[i][0]][son_node[i][1]]) 
                    ) {
                        OPEN.unshift([h,[son_node[i][0],son_node[i][1],cur_node[2] + 1]]);
                        OPEN.sort((a,b) => { return a[0] - b[0]; });
                        MAP_OPEN[son_node[i][0]] = MAP_OPEN[son_node[i][0]] ? MAP_OPEN[son_node[i][0]] : [];
                        MAP_OPEN[son_node[i][0]][son_node[i][1]] = 1;
                    } else {
                        if(MAP_OPEN[son_node[i][0]][son_node[i][1]]) {
                            for(let j = 0; j < OPEN.length; j++) {
                                if(OPEN[j][1][0] == son_node[i][0] && OPEN[j][1][1] == son_node[i][1]) {
                                    if(h < OPEN[j][0]) {
                                        OPEN[j][0] = h; OPEN[j][1][2] = cur_node[2] + 1;
                                        OPEN.sort((a,b)=>{ return a[0] - b[0];});
                                    }
                                    break;
                                }
                            }
                        } else if(MAP_CLOSED[son_node[i][0]][son_node[i][1]]) {
                            for(let j = 0; j < CLOSED.length; j++) {
                                if(CLOSED[j][1][0] == son_node[i][0] && CLOSED[j][1][1] == son_node[i][1]) {
                                    if(h < CLOSED[j][0]) {
                                        let t_node = CLOSED.splice(j,1)[0];
                                        MAP_CLOSED[t_node[1][0]][t_node[1][1]] = 0;
                                        t_node[0] = h; t_node[1][2] = cur_node[2] + 1;
                                        OPEN.unshift(JSON.parse(JSON.stringify(t_node)));
                                        MAP_OPEN[t_node[1][0]][t_node[1][1]] = 1;
                                        OPEN.sort((a,b)=>{ return a[0] - b[0];});
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    for(let i = 1; i < trees.length; i++) {
        let dis = A_STAR(trees[i-1][1][0], trees[i-1][1][1], trees[i][1][0], trees[i][1][1]);
        if(dis == -1) {
            return -1;
        }
        /*console.log("target:" + trees[i-1][1]);
        console.log("source:" + trees[i][1]);
        console.log("step:" + dis);
        **/
        ans += dis;
    }
    return ans;
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值