675. 为高尔夫比赛砍树

原题链接:675. 为高尔夫比赛砍树

 

solution:

广度优先搜索,首先将所有点按高度从小到大进行排序,每两个点更新一次最大距离。

时间复杂度O(m^2 + n^2) 

bfs函数返回start到end的最短距离

class Solution {
public:
    vector<vector<int>> g;
    int m,n;
    const int INF = 0x3f3f3f3f;


    struct Tree {
        int x,y,h;  //坐标和高度

        bool operator< (const Tree& t) const {  //重载小于号
            return h < t.h;
        }
    };

    int bfs(struct Tree start,struct Tree end) {
        if(start.x == end.x && start.y == end.y) return 0;  //相等返回0
        queue<Tree> que;
        vector<vector<int>> dist(m, vector<int> (n, INF));  //初始化距离为无穷大
        que.push(start);
        int dx[] = {-1,0,1,0},dy[] = {0,-1,0,1};
        dist[start.x][start.y] = 0; //起点距离为0
        while(que.size()) {
            auto t = que.front();
            que.pop();
            for(int i = 0;i < 4;i++) {
                int a = t.x + dx[i],b = t.y + dy[i];
                if(a >= 0 && a < m && b >= 0 && b < n && g[a][b]) {
                    if(dist[a][b] > dist[t.x][t.y] + 1) {
                        dist[a][b] = dist[t.x][t.y] + 1;
                        if(a == end.x && b == end.y) return dist[a][b];
                        que.push({a,b});
                    }
                }
            }
        }
        return -1;
    }

    int cutOffTree(vector<vector<int>>& forest) {
        g = forest;
        m = forest.size(),n = forest[0].size(); //m行n列

        vector<Tree> trees;
        for(int i = 0;i < m;i++)
            for(int j = 0;j < n;j++) {
                if(g[i][j] > 1) trees.push_back({i,j,g[i][j]});   //保存每个高度大于1的点
            }
        sort(trees.begin(),trees.end());    //按高度从小到大排序

        Tree last = {0,0,0};
        int path = 0;   //保存砍树最短距离
        for(int i = 0;i < trees.size();i++) {
            int t = bfs(last,trees[i]); //t保存last到trees[i]的最短距离
            if(t == -1) return -1;  //如果t == -1,表示无法抵达
            path += t;
            last = trees[i];
        }
        return path;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值