你被请来给一个要举办高尔夫比赛的树林砍树. 树林由一个非负的二维数组表示, 在这个数组中:
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;
}
}