13. 機器人的運動范圍(Python)

難度:★★★☆☆
類型:數(shù)組
方法:深度優(yōu)先搜索or寬度優(yōu)先搜索

題目

力扣鏈接請移步【本題傳送門】
更多力扣題解請移步【力扣-劍指offer目錄】

地上有一個m行n列的方格,從坐標(biāo) [0,0] 到坐標(biāo) [m-1,n-1] 。一個機器人從坐標(biāo) [0, 0] 的格子開始移動,它每次可以向左、右、上、下移動一格(不能移動到方格外),也不能進入行坐標(biāo)和列坐標(biāo)的數(shù)位之和大于k的格子。例如,當(dāng)k為18時,機器人能夠進入方格 [35, 37] ,因為3+5+3+7=18。但它不能進入方格 [35, 38],因為3+5+3+8=19。請問該機器人能夠到達多少個格子?

示例 1:

輸入:m = 2, n = 3, k = 1
輸出:3

示例 2:

輸入:m = 3, n = 1, k = 0
輸出:1
提示:

1 <= n,m <= 100
0 <= k <= 20

解答

方案1:深度優(yōu)先搜索

我們把一些功能塊封裝成函數(shù),便于理解和使用:

neighbours(r, c):用于獲取某個點處的所有相鄰合法點(不越界)坐標(biāo);
digit_sum(n):計算某個數(shù)字的各位數(shù)字之和;
can_arrive(r, c):判斷某個點按照題目要求是否可到達;

其他注意事項:

  • 遍歷過程中使用集合footprint來記錄走過的點,避免重復(fù)遍歷造成死循環(huán);
  • 深度優(yōu)先搜索函數(shù)dfs使用遞歸實現(xiàn),開頭寫清終止條件,并在通過校驗后對相鄰點進行遍歷遞歸;
  • 按照題目要求,最后返回足跡集合的長度即可。
class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:

        def neighbours(r, c):
            """
            獲取(r, c)所有合法相鄰位置坐標(biāo)
            """
            for dr, dc in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < m and 0 <= nc < n:
                    yield nr, nc

        def digit_sum(n):
            """
            計算數(shù)字n各個位置之和
            """
            s = 0
            while n:
                n, r = divmod(n, 10)
                s += r
            return s

        def can_arrive(r, c):
            """
            判斷(r, c)位置是否可以到達
            """
            return digit_sum(r) + digit_sum(c) <= k

        footprint = set()           # 足跡集合
        def dfs(r, c):
            if (r, c) in footprint or not can_arrive(r, c):
                return
            footprint.add((r, c))
            for nr, nc in neighbours(r, c):
                dfs(nr, nc)

        dfs(0, 0)
        # print(footprint)
        return len(footprint)           # 所有可以到達的位置的個數(shù)



s = Solution()
print(s.movingCount(2, 3, 1))
print(s.movingCount(3, 1, 0))

方案2:寬度優(yōu)先搜索

我們把上面所述的算法用寬度優(yōu)先搜索改寫,使用隊列就可以實現(xiàn)。

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:

        def neighbours(r, c):
            """
            獲取(r, c)所有合法相鄰位置坐標(biāo)
            """
            for dr, dc in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < m and 0 <= nc < n:
                    yield nr, nc

        def digit_sum(n):
            """
            計算數(shù)字n各個位置之和
            """
            s = 0
            while n:
                n, r = divmod(n, 10)
                s += r
            return s

        def can_arrive(r, c):
            """
            判斷(r, c)位置是否可以到達
            """
            return digit_sum(r) + digit_sum(c) <= k

        queue = [(0, 0)]
        footprint = set()
        while queue:
            r, c = queue.pop(0)
            if (r, c) in footprint or not can_arrive(r, c):
                continue
            footprint.add((r, c))
            for nr, nc in neighbours(r, c):
                queue.append((nr, nc))

        return len(footprint)           # 所有可以到達的位置的個數(shù)


s = Solution()
print(s.movingCount(2, 3, 1))
print(s.movingCount(3, 1, 0))

如有疑問或建議,歡迎評論區(qū)留言~

有關(guān)更多力扣中等題的python解決方案,請移步【力扣面試題解析】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容