题目内容 地上有一个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:
1 2 输入:m = 2, n = 3, k = 1 输出:3
示例 2:
1 2 输入:m = 3, n = 1, k = 0 输出:1
提示:
1 2 1 <= n,m <= 100 0 <= k <= 20
解法一:深度优先搜索 思路:这道题很像招式_剑指 Offer 12. 矩阵中的路径 ,所以一开始就是打算套壳
比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public: unordered_map <int,unordered_map <int,int>> cmap; int getNumLength(int num){ int start = 1; int res = 0; while(num>start){ res ++; start *= 10; } return res; } int caculNum(int num){ int start = pow(10,getNumLength(num)); int res = 0; while(start >= 1){ res += (num / start % 10); start /= 10; } return res; } int cmax(int i,int j){ return i >= j ? i:j; } int dfs(int i,int j,int &k,int &m,int &n){ if(i>=m || i<0 || j>= n || j<0 || k< caculNum(i)+caculNum(j) || cmap[i][j] == 1){ return 0; } //cout<<i<<" "<<j <<" "<<k<<endl; cmap[i][j] = 1; int res = 1 + cmax(max(dfs(i-1,j,k,m,n),dfs(i+1,j,k,m,n)),cmax(dfs(i,j-1,k,m,n),dfs(i,j+1,k,m,n))); cmap[i][j] = 0; return res; } int movingCount(int m, int n, int k) { return dfs(0,0,k,m,n); } };
但是,发现有个问题,提交后结果总比实际结果要少。 于是构造一个测试用例:
理论上应该是有这三个点
在纸上模拟了一下,发现一个问题:招式_剑指 Offer 12. 矩阵中的路径 ,这道题不允许后退;但是在这道题是可以后退的,也就是说可以像走迷宫一样自由查找路径,好吧,那就修改一下代码。
修改代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 class Solution { private: unordered_map <int,unordered_map <int,int>> cmap; int getNumLength(int num){ int start = 1; int res = 0; while(num>start){ res ++; start *= 10; } return res; } int caculNum(int num){ int start = pow(10,getNumLength(num)); int res = 0; while(start >= 1){ res += (num / start % 10); start /= 10; } return res; } int dfs(int i,int j,int &k,int &m,int &n){ if(i>=m || i<0 || j>= n || j<0 || k< caculNum(i)+caculNum(j) || cmap[i][j] == 1){ return 0; } cmap[i][j] = 1; int res = 1; res += dfs(i-1,j,k,m,n); cmap[i-1][j] = 1; res += dfs(i+1,j,k,m,n); cmap[i+1][j] = 1; res += dfs(i,j-1,k,m,n); cmap[i][j-1] = 1; res += dfs(i,j+1,k,m,n); cmap[i][j+1] = 1; return res; } public: int movingCount(int m, int n, int k) { return dfs(0,0,k,m,n); } };
也就是说,我在dfs进行了修改,之前是挑选一条能走最远的路:
1 int res = 1 + cmax(max(dfs(i-1,j,k,m,n),dfs(i+1,j,k,m,n)),cmax(dfs(i,j-1,k,m,n),dfs(i,j+1,k,m,n)));
现在变成了每条路都走一下,同时,为了防止走过的路被重复计算,于是加个剪枝:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cmap[i][j] = 1; int res = 1; res += dfs(i-1,j,k,m,n); cmap[i-1][j] = 1; res += dfs(i+1,j,k,m,n); cmap[i+1][j] = 1; res += dfs(i,j-1,k,m,n); cmap[i][j-1] = 1; res += dfs(i,j+1,k,m,n); cmap[i][j+1] = 1; return res;
运行结果,能通过但是不是很理想哎:
1 2 3 4 5 6 7 8 9 10 11 12 执行用时: 16 ms , 在所有 C++ 提交中击败了 6.23% 的用户 内存消耗: 15.2 MB , 在所有 C++ 提交中击败了 5.01% 的用户 通过测试用例: 49 / 49
好吧,对caclu这个函数进行改造,用于计算个位十位的加和用
1 2 3 4 5 6 7 int caculNum(int x) { int res=0; for (; x; x /= 10) { res += x % 10; } return res;
同时把caculNum的决策放到最后面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Solution { private: unordered_map <int,unordered_map <int,int>> cmap; int caculNum(int x) { int res=0; for (; x; x /= 10) { res += x % 10; } return res; } int dfs(int i,int j,int &k,int &m,int &n){ if(i>=m || i<0 || j>= n || j<0 || cmap[i][j] == 1) return 0; if(k<caculNum(i)+caculNum(j)) return 0; cmap[i][j] = 1; int res = 1; res += dfs(i-1,j,k,m,n); cmap[i-1][j] = 1; res += dfs(i+1,j,k,m,n); cmap[i+1][j] = 1; res += dfs(i,j-1,k,m,n); cmap[i][j-1] = 1; res += dfs(i,j+1,k,m,n); cmap[i][j+1] = 1; return res; } public: int movingCount(int m, int n, int k) { return dfs(0,0,k,m,n); } };
结果,好像是提升了一点点
1 2 3 4 5 6 7 8 9 10 11 12 执行用时: 8 ms , 在所有 C++ 提交中击败了 13.00% 的用户 内存消耗: 14.9 MB , 在所有 C++ 提交中击败了 5.01% 的用户 通过测试用例: 49 / 49
突然发现我是傻逼,dfs应该这样写
1 2 3 4 5 6 int dfs(int i,int j,int &k,int &m,int &n){ if(i>=m || i<0 || j>= n || j<0 || cmap[i][j] == 1 || k<caculNum(i)+caculNum(j)) return 0; cmap[i][j] = 1; return 1+dfs(i-1,j,k,m,n)+ dfs(i+1,j,k,m,n)+ dfs(i,j-1,k,m,n)+ dfs(i,j+1,k,m,n); }