leetcode 劍指offer 13 機器人的運動範圍
阿新 • • 發佈:2020-12-28
問題描述:
地上有一個m行n列
的方格,從座標 [0,0]
到座標 [m-1,n-1]
。一個機器人從座標 [0, 0]
的格子開始移動,它每次可以向左、右、上、下移動一格(不能移動到方格外),也不能進入行座標和列座標的數位之和大於k
的格子。例如,當k
為18
時,機器人能夠進入方格 [35, 37]
,因為3+5+3+7=18
。但它不能進入方格[35, 38]
,因為3+5+3+8=19
。請問該機器人能夠到達多少個格子?
解題思路:
本題與矩陣中的路徑類似,是典型的搜尋 & 回溯問題。在介紹回溯演算法演算法前,為提升計算效率,首先講述兩項前置工作:數位之和計算、可達解分析 。
數位之和計算:
設一數字x
//
,求餘符號⊙
,則有:
- x⊙10:得到x的個位數字;
- x//10: 令x的十進位制數向右移動一位,即刪除個位數字。
由於機器人每次只能移動一格(即只能從x
運動至x±1
),因此每次只需計算x
到x±1
的數位和增量。本題說明1≤n,m≤100
,以下公式僅在此範圍適用。
(x + 1) % 10 != 0 ? s_x + 1 : s_x - 8;
方法:廣度優先遍歷 BFS
-
BFS/DFS : 兩者目標都是遍歷整個矩陣,不同點在於搜尋順序不同。
-
DFS 是朝一個方向走到底,再回退,以此類推;
-
BFS 則是按照“平推”的方式向前搜尋。
-
-
BFS 實現: 通常利用佇列實現廣度優先遍歷。
演算法解析:
-
初始化: 將機器人初始點 (0, 0)(0,0) 加入佇列 queue ;
-
迭代終止條件: queue 為空。代表已遍歷完所有可達解。
-
迭代工作:
- 單元格出隊: 將隊首單元格的 索引、數位和 彈出,作為當前搜尋單元格。
- 判斷是否跳過: 若 ① 行列索引越界 或 ② 數位和超出目標值 k 或 ③ 當前元素已訪問過 時,執行 continue 。
- 標記當前單元格 :將單元格索引 (i, j) 存入 Set visited 中,代表此單元格 已被訪問過 。
- 單元格入隊: 將當前元素的 下方、右方 單元格的 索引、數位和 加入 queue 。
-
返回值: Set visited
len(visited)
,即可達解的數量。
PS:使用了輔助變數 res 統計可達解數量;
class Solution {
public:
int movingCount(int m, int n, int k) {
vector<vector<bool>> v(m, vector<bool>(n, 0));
int res = 0;
queue<vector<int>> que;
que.push({0, 0, 0, 0});
while(!que.empty())
{
auto x = que.front();
que.pop();
int i = x[0], j = x[1], si = x[2], sj = x[3];
if (i >= m || j >= n || k < si + sj || v[i][j]) continue;
++res;
v[i][j] = true;
que.push({i, j + 1, si, (j + 1) % 10 ? (sj + 1) : (sj - 8)});
que.push({i + 1, j, (i + 1) % 10 ? (si + 1) : (si - 8), sj});
}
return res;
}
};