675. 为高尔夫比赛砍树 bfs

你被请来给一个要举办高尔夫比赛的树林砍树. 树林由一个非负的二维数组表示, 在这个数组中:
0 表示障碍,无法触碰到.
1 表示可以行走的地面.
比1大的数 表示一颗允许走过的树的高度.
你被要求按照树的高度从低向高砍掉所有的树,每砍过一颗树,树的高度变为1。
你将从(0,0)点开始工作,你应该返回你砍完所有树需要走的最小步数。 如果你无法砍完所有的树,返回 -1 。
可以保证的是,没有两棵树的高度是相同的,并且至少有一颗树需要你砍。

思路,先用Map存下所有的树的节点,然后从小到大对每个节点用一次bfs即可,
从起点开始,找第一棵最矮的树的最短路径,下次以该树的坐标为起点,继续找第二矮的树....
class Solution {
    int[] dx={0,0,1,-1};
    int[] dy={1,-1,0,0};
    static class Idx{
        int x;
        int y;
        int cnt;
        public Idx(int x, int y, int cnt) {
            this.x = x;
            this.y = y;
            this.cnt = cnt;
        }
    }
    public int cutOffTree(List<List<Integer>> forest) {
        int n=forest.size();
        int m=forest.get(0).size();
        Map<Integer,Idx> map=new TreeMap<Integer,Idx>();
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                int hi=forest.get(i).get(j);
                if(hi>1){
                    map.put(hi,new Idx(i,j,0));
                }
            }
        }
        int res=0;
        Idx st=new Idx(0,0,0);
        for(Idx cur:map.values()){
           int dict=bfs(forest,st,cur);
           if(dict<0){
               return -1;
           }
           res+=dict;
           st=cur;
        }
        return res;
    }
    public int bfs(List<List<Integer>> forest,Idx st,Idx ed){
        int n=forest.size();
        int m=forest.get(0).size();
        boolean[][] vis=new boolean[n][m];
        Queue<Idx> queue=new LinkedList<Idx>();
        queue.add(st);
        vis[st.x][st.y]=true;
        st.cnt=0;
        while (!queue.isEmpty()){
            Idx cur=queue.poll();
            if(cur.x==ed.x&&cur.y==ed.y){
                return cur.cnt;
            }
            for(int i=0;i<4;++i){
                int xi=cur.x+dx[i];
                int yi=cur.y+dy[i];
                if(xi>=0&&yi>=0&&xi<n&&yi<m&&forest.get(xi).get(yi)!=0&&!vis[xi][yi]){
                    vis[xi][yi]=true;
                    queue.add(new Idx(xi,yi,cur.cnt+1));
                }
            }
        }
        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值