2022-05-24 bfs

111 阅读2分钟

为高尔夫比赛砍树

你被请来给一个要举办高尔夫比赛的树林砍树。树林由一个 m x n 的矩阵表示, 在这个矩阵中:

0 表示障碍,无法触碰 1 表示地面,可以行走 比 1 大的数 表示有树的单元格,可以行走,数值表示树的高度 每一步,你都可以向上、下、左、右四个方向之一移动一个单位,如果你站的地方有一棵树,那么你可以决定是否要砍倒它。

你需要按照树的高度从低向高砍掉所有的树,每砍过一颗树,该单元格的值变为 1(即变为地面)。

你将从 (0, 0) 点开始工作,返回你砍完所有树需要走的最小步数。 如果你无法砍完所有的树,返回 -1 。

可以保证的是,没有两棵树的高度是相同的,并且你至少需要砍倒一棵树。

image.png

个人题解

class Solution {
    private List<Node> next = new ArrayList<>();
    private Integer xMax;
    private Integer yMax;

    {
        next.add(new Node(-1, 0, 0));
        next.add(new Node(1, 0, 0));
        next.add(new Node(0, -1, 0));
        next.add(new Node(0, 1, 0));
    }

    public static void main(String[] args) {

        Solution solution = new Solution();
        List<List<Integer>> lists = new ArrayList<>();

        ArrayList<Integer> list = new ArrayList<>();
        list.add(4);
        list.add(2);
        list.add(3);
        lists.add(list);

        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(0);
        list1.add(0);
        list1.add(1);
        lists.add(list1);

        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(7);
        list2.add(6);
        list2.add(5);
        lists.add(list2);

        int i = solution.cutOffTree(lists);
        System.out.println(i);

    }

    public int cutOffTree(List<List<Integer>> forest) {
        xMax = forest.get(0).size() - 1;
        yMax = forest.size() - 1;
        ArrayList<Node> nodes = new ArrayList<>();
        HashMap<String, Node> passedMap = new HashMap<>();// key x,y
        //按照树高度找到路径
        for (int i = 0; i < forest.size(); i++) {
            for (int j = 0; j < forest.get(0).size(); j++) {
                Integer value = forest.get(i).get(j);
                Node node = new Node(j, i, value);
                if (value > 1) {
                    nodes.add(node);
                }
                String key = j + "," + i;
                passedMap.put(key, node);
            }
        }
        Collections.sort(nodes, (a, b) -> {
            return a.getValue() - b.getValue();
        });

        Node start = new Node(0, 0, 0);
        Integer result = 0;

        for (Node node : nodes) { //累加每一步路径和
            Integer length = bfs(start, node, passedMap);
            if (length == -1) {
                return length;
            }
            result += length;
            start = node;
        }

        return result;

    }

    private Integer bfs(Node start, Node end, HashMap<String, Node> passedMap) {
        if (start.equals(end)) {
            return 0;
        }
        Integer result = 0;
        Queue<Node> queue = new LinkedList<>();
        queue.add(start);
        String keyStart = start.getX() + "," + start.getY();

        HashMap<String, Boolean> map = new HashMap<>();
        map.put(keyStart, true);


        while (queue.size() > 0) {

            int size = queue.size();
            for (int i = 0; i < size; i++) {
                Node poll = queue.poll();
                //下一步能到达的坐标
                for (Node nextStep : next) {
                    Node nextNode = new Node();
                    nextNode.setX(poll.getX() + nextStep.getX());
                    nextNode.setY(poll.getY() + nextStep.getY());
                    String keyNext = nextNode.getX() + "," + nextNode.getY();

                    if (nextNode.equals(end)) {//到达下一位置
                        return ++result;
                    }

                    if (!passedMap.containsKey(keyNext)
                            || (map.containsKey(keyNext) && map.get(keyNext))
                            || passedMap.get(keyNext).getValue() == 0) {//到达地图外或已走过位置或为非障碍路段
                        continue;
                    }

                    map.put(keyNext, true);
                    queue.add(nextNode);
                }
            }

            result++;
        }

        return -1;
    }


    private class Node {
        private Integer x;
        private Integer y;
        private Integer value;
        private Boolean passed;

        public Node() {
        }

        public Boolean getPassed() {
            return passed;
        }

        public void setPassed(Boolean passed) {
            this.passed = passed;
        }

        public Node(Integer x, Integer y, Integer value) {
            this.x = x;
            this.y = y;
            this.value = value;
            this.passed = false;
        }

        public Integer getX() {
            return x;
        }

        public void setX(Integer x) {
            this.x = x;
        }

        public Integer getY() {
            return y;
        }

        public void setY(Integer y) {
            this.y = y;
        }

        public Integer getValue() {
            return value;
        }

        public void setValue(Integer value) {
            this.value = value;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Node node = (Node) o;
            return x == node.x && y == node.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }
}