题目要求:
地上有一个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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的思路:
先把所有符合条件的点,也就是数位之和i+数位之和j <= k的点标为0。不符合条件的数位标为2。然后从[0][0]开始搜索,能到的、而且是0的地方标为1。
转换成常规的广度优先搜索问题,借鉴之前的岛屿面积和走迷宫问题。
这里值得注意的是,由于从[0][0]开始走,故只需要考虑向下和向右的两个方向。
int shuwei(int x) {//求数位
int ans = 0;
while ( x )
{
ans += x % 10;
x /= 10;
}
return ans;
}
int movingCount(int m, int n, int k) {
vector<vector<int>> map;
for (size_t i = 0; i < m; i++) { //为每个格子检查下是否符合要求
vector <int> eve;
for (size_t j = 0; j < n; j++)
{
if (shuwei(i) + shuwei(j) <= k)
eve.push_back(0);
else
eve.push_back(2);
}
map.push_back(eve);
}
//init
stack<int> stacki;
stack<int> stackj; // 两个栈分别储存 i、j 坐标
stacki.push(0); stackj.push(0);
int add[2][2]{ {0,1},{1,0}};
while (!stacki.empty()) {
int cur_i = stacki.top(), cur_j = stackj.top();
stacki.pop(); stackj.pop();
if (cur_i >= m || cur_j >= n || map[cur_i][cur_j] != 0)
//只向右或向下走,则i、j必大于0,如果合法就把它的下边第一个和右边第一个压入栈中
continue;
map[cur_i][cur_j] = 1; ///标记这个区域可以进入
for (size_t z = 0; z < 2; z++)
{
int next_i = cur_i + add[z][0];
int next_j = cur_j + add[z][1];
stacki.push(next_i);
stackj.push(next_j);
}
}
int count = 0;
for (size_t i = 0; i < m; i++) //最后遍历一遍有几个符合条件
for (size_t j = 0; j < n; j++)
{
if (map[i][j] == 1)
count++;
}
return count;
}
官方解答 :
方法一:类似思想
class Solution {
// 计算 x 的数位之和
int get(int x) {
int res=0;
for (; x; x /= 10) {
res += x % 10;
}
return res;
}
public:
int movingCount(int m, int n, int k) {
if (!k) return 1;
queue<pair<int,int> > Q; // 由两个数作为基本元素组成的队列
// 向右和向下的方向数组
int dx[2] = {0, 1};
int dy[2] = {1, 0};
vector<vector<int> > vis(m, vector<int>(n, 0)); //构造m*n0矩阵
Q.push(make_pair(0, 0)); //放入把起始点00作为首元素放入队列
vis[0][0] = 1;
int ans = 1;
while (!Q.empty()) {
auto x = Q.front().first; // 这么取出 pair 中的数
auto y = Q.front().second;
Q.pop();
for (int i = 0; i < 2; ++i) {
int tx = dx[i] + x;
int ty = dy[i] + y;
if (tx < 0 || tx >= m || ty < 0 || ty >= n || vis[tx][ty] || get(tx) + get(ty) > k) continue;
Q.push(make_pair(tx, ty));
vis[tx][ty] = 1;
ans++;
}
}
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/ji-qi-ren-de-yun-dong-fan-wei-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
其中需要学习的有 二维vector向量的表示方法:
1.vector<vector > vis(m, vector(n, 0)) vis 即为m行,每行是n个0 的vector < int > 的二维vector int 数组。
2.pair与make_pair的用法,以及对于pair对象通过.first \ .second 取出第一、第二个元素
方法二:
递推,由于从0 0 出发,则一个块能到,则必须满足它的上方可以到或者它的下方可以到,遍历即可。
int get(int x) {
int res=0;
for (; x; x /= 10){
res += x % 10;
}
return res;
}
public:
int movingCount(int m, int n, int k) {
if (!k) return 1;
vector<vector<int> > vis(m, vector<int>(n, 0)); //已经把所有数归0了
int ans = 1;
vis[0][0] = 1;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if ((i == 0 && j == 0) || get(i) + get(j) > k) continue;
// 边界判断
if (i - 1 >= 0) vis[i][j] |= vis[i - 1][j];
if (j - 1 >= 0) vis[i][j] |= vis[i][j - 1]; //如果前边或上边有一个能走到,而这个又符合条件,那么即可走到
ans += vis[i][j];
}
}
return ans;
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/ji-qi-ren-de-yun-dong-fan-wei-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
需要学习的有
**1.与、异或、或运算符,即&、^、| **