为什么这种DFS方式不起作用?

时间:2017-11-06 10:04:27

标签: python algorithm

问题描述:

给定一个2D网格,每个单元格都是墙'W',敌人'E'或空'0'(数字0),使用一个炸弹返回你可以杀死的最大敌人。

炸弹会从种植点杀死同一行和列中的所有敌人,直到它撞到墙上,因为墙太强而不能被摧毁。

请注意,您只能将炸弹放在空单元格中。

Example:
For the given grid

0 E 0 0
E 0 W E
0 E 0 0

return 3. (Placing a bomb at (1,1) kills 3 enemies)

我的DFS解决方案:

def maxKilledEnemies(grid):
    """
    :type grid: List[List[str]]
    :rtype: int
    """
    l_row, l_col = len(grid), len(grid[0])
    visited = [[False] * l_col for _ in range(l_row)] #using this array to avoid duplicate traverse.

    def dfs(i, j):
        if 0 <= i < l_row and 0 <= j < l_col and not visited[i][j]:
            visited[i][j] = True
            if grid[i][j] == 'W': #wall return 0
                return 0
            elif grid[i][j] == '0': #0 means we just ignore this cell and traverse it adjacents
                top_val = dfs(i - 1, j)
                down_val = dfs(i + 1, j)
                left_val = dfs(i, j - 1)
                right_val = dfs(i, j + 1)
                return left_val + right_val + top_val + down_val
            elif grid[i][j] == 'E': # Enemy and we add it by 1
                top_val = dfs(i - 1, j)
                down_val = dfs(i + 1, j)
                left_val = dfs(i, j - 1)
                right_val = dfs(i, j + 1)
                return left_val + right_val + top_val + down_val + 1
        return 0

    ret = [0]
    for i in range(l_row):
        for j in range(l_col):
            if not visited[i][j] and grid[i][j] == '0':
                val = dfs(i, j)
                ret[0] = max(val, ret[0])
    return ret[0]

Solution().maxKilledEnemies([["0","E","0","0"],["E","0","W","E"],["0","E","0","0"]]) #return 4 but expect 3.

这个想法很简单,对于num为0的每个单元格,我们遍历4 方向(上/下/左/右)。

我知道还有其他方法可以更聪明地解决它。但我想弄清楚为什么我的方式不起作用?

2 个答案:

答案 0 :(得分:0)

您的代码中至少有三个错误:

  • 在每个递归步骤中,您将探索所有可能的方向。这使得您的搜索行为类似于洪水填充,但您希望从您仅检查的炸弹位置向所有方向开始。之后,按给定方向递归(或迭代搜索)。
  • 你不会检查可能的炸弹位置是否为空,所以你的代码可以将炸弹放在敌人身上。
  • 您不会在搜索之间重置访问过的数组,因此实际上只会评估单元格(0,0)。

一种解决方案是拥有两个功能,

  • 一个可能的炸弹位置。检查此处是否为空。如果是的话,通过递减北,东,南和西来计算受害者。
  • 一个用于&#34;射线&#34;炸弹沿着给定的方向行进并计算敌人直到你撞到墙壁。由于光线只在一个方向传播,因此您不再需要访问过的阵列。

这不是第一次深度搜索,所以不是递归地调用第二个函数,而是可以使用循环。

答案 1 :(得分:0)

可能是因为使用DFS不是解决方案。当您使用DFS时,您搜索网格中的所有可到达空格但是对于您的问题,您应该只搜索直接水平或垂直空格。 例如:在[0] [0]处使用DFS时,您将找到所有敌人,而不仅仅是[0] [1]和[1] [0]中的所有敌人。