【剑指 Offer 13. 机器人的运动范围 中等】
【剑指 Offer 13. 机器人的运动范围 中等】
地上有一个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。请问该机器人能够到达多少个格子?
示例 1:
输入:m = 2, n = 3, k = 1
输出:3
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
思路:
最基本的方法是采用dfs暴力搜索每一个可行的路径,并记录访问过的格子的数量。代码如下:
class Solution { public: int movingCount(int m, int n, int k) { vector<vector<bool>> visited(m, vector<bool>(n, 0)); return dfs(0, 0, visited, m, n, k); } int sums(int x) { int s = 0; while(x != 0) { s += x % 10; x = x / 10; } return s; } private: int dfs(int i, int j, vector<vector<bool>> &visited, int m, int n, int k) { if(i < 0 || j < 0 || i >= m || j >= n || k < sums(i) + sums(j) || visited[i][j]) return 0; visited[i][j] = true; return 1 + dfs(i + 1, j,visited, m, n, k) + dfs(i, j + 1, visited, m, n, k) + dfs(i - 1, j, visited, m, n, k) + dfs(i, j - 1, visited, m, n, k); } };
该代码可以通过。
但是其实机器人仅通过向右和向下行走,就可到达所有可行解。因此dfs可以修改如下:
int dfs(int i, int j, vector<vector<bool>> &visited, int m, int n, int k) { if(i < 0 || j < 0 || i >= m || j >= n || k < sums(i) + sums(j) || visited[i][j]) return 0; visited[i][j] = true; return 1 + dfs(i + 1, j,visited, m, n, k) + dfs(i, j + 1, visited, m, n, k); }
同样的也可以基于广度优先遍历(BFS)进行实现,DFS朝一个方向一直遍历走到底,然后回溯;而BFS则类似于层次遍历,将当前节点的每个邻接点都访问完毕后,再访问下一层,需要借助一个队列记录访问过的邻接点。
class Solution { public: int sums(int x) { int res = 0; while(x != 0) { res += x % 10; x /= 10; } return res; } int movingCount(int m, int n, int k) { vector<vector<bool>> visited(m, vector<bool>(n, false)); queue<vector<int>> q; q.push({0, 0}); int res = 0; while(!q.empty()) { vector<int> cur = q.front(); q.pop(); int i = cur[0], j = cur[1]; if(i >= m || j >= n || sums(i) + sums(j) > k || visited[i][j] ) continue; res += 1; visited[i][j] = true; q.push({i + 1, j}); q.push({i, j + 1}); } return res; } };