LeetCode--[广度优先搜索]675. 为高尔夫比赛砍树

你被请来给一个要举办高尔夫比赛的树林砍树. 树林由一个非负的二维数组表示, 在这个数组中:

0 表示障碍,无法触碰到.
1 表示可以行走的地面.
比1大的数 表示一颗允许走过的树的高度.
你被要求按照树的高度从低向高砍掉所有的树,每砍过一颗树,树的高度变为1。

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

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

示例 1:

输入:
[
[1,2,3],
[0,0,4],
[7,6,5]
]
输出: 6

示例 2:

输入:
[
[1,2,3],
[0,0,0],
[7,6,5]
]
输出: -1

示例 3:

输入:
[
[2,3,4],
[0,0,5],
[8,7,6]
]
输出: 6

解释: (0,0) 位置的树,你可以直接砍去,不用算步数

扫描二维码关注公众号,回复: 2360004 查看本文章

提示: 矩阵大小不会超过 50x50 。

解答

采用广度优先搜索,首先把树取出来,然后再排序,然后从起点开始搜索,记录已经修剪到的树
状态:当前修剪的树的编号。下一次修剪的树的编号是在此基础上加1
若当前此状态曾经访问过,则跳过此状态。需要用一个数组存放状态,数组的大小与forest大小相同。

# -*- coding: utf-8 -*-
from collections import deque, namedtuple

TreeNode = namedtuple('TreeNode', ['row','col','id'])
class Solution:
    def cutOffTree(self, forest):
        """
        :type forest: List[List[int]]
        :rtype: int
        """
        # 采用广度优先搜索,首先把树取出来,然后再排序,然后从起点开始搜索,记录已经修剪到的树
        # 状态:当前修剪的树的编号。下一次修剪的树的编号是在此基础上加1
        # 若当前此状态曾经访问过,则跳过此状态。需要用一个数组存放状态,数组的大小与forest大小相同

        # 读取树,并排序
        M = len(forest)
        N = len(forest[0])
        tree_lst = []
        for i in range(M):
            for j in range(N):
                c = forest[i][j]
                if c > 1:
                    tree_lst.append(c)
        tree_lst = sorted(tree_lst)
        nt = len(tree_lst)
        # 当前已经走的边长度
        length_step = 0

        # 保存状态
        visited = [[-2 for i in range(N)] for j in range(M)]
        # 初始化的队列
        q = deque()

        if tree_lst[0] == forest[0][0]:
            q.append(TreeNode(0, 0, 0))
            visited[0][0] = 0
        else:
            q.append(TreeNode(0, 0, -1))

        # 遍历的方向
        dirs = [(0, -1),(0, 1),(1, 0), (-1, 0)]

        while q:
            nq = len(q)
            while nq:
                nq = nq -1
                node = q.popleft()
                # 判断是否已经砍了所有树
                if node.id == nt -1:
                    return length_step
                for d in dirs:
                    row = node.row + d[0]
                    col = node.col + d[1]
                    cur_id = node.id
                    # 是否越界
                    if row < 0 or row >= M or col < 0 or col >= N:
                        continue
                    c = forest[row][col]
                    # 是否是墙
                    if c == 0:
                        continue
                    # 是否是树且是接下来要砍的树
                    if c > 1 and tree_lst.index(c) == node.id + 1:
                        # 记录当前砍到了第几个树
                        cur_id = node.id + 1
                    # 判断当前状态是否曾经到达过,若到达过,则此前到达的时候肯定比此次到达更优,则跳过;否则加入队列
                    if visited[row][col]>= cur_id:
                        continue
                    visited[row][col] = cur_id
                    q.append(TreeNode(row, col, cur_id))
            # 下一层
            length_step = length_step + 1
        return -1


可以用C++写,目前用python写的速度都太慢。

猜你喜欢

转载自blog.csdn.net/u014230646/article/details/81189405
今日推荐