地上有一个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。请问该机器人能够到达多少个格子?
思路: 这个问题其实用bfs和dfs都很好做,和矩阵迷宫的做法其实是一样的,位数相加不能超过k其实就是矩阵中的障碍。题目说的可以上下左右四个方向,其实只需要向下和向右即可,而向上和向左其实和下,右是重叠的。
1 dfs
dfs其实就是一直向下递归, (i,j)这个位置可以从 dfs(i-1,j)+dfs(i,j-1)+dfs(i+1,j)+dfs(i,j+1)转移过来,最后 return的是1+dfs(i-1,j,m,n,k)+dfs(i,j-1,m,n,k)+dfs(i+1,j,m,n,k)+dfs(i,j+1,m,n,k),结果是要+1,因为要加上当前i,j的位置。
这里需要注意的是需要一个vis数组记录矩阵的某个元素是否被访问过。
class Solution {
public:
//1+dfs(i-1,j)+dfs(i,j-1)+dfs(i+1,j)+dfs(i,j+1)
vector<vector<bool>> vis;
int countnum(int n)
{
int ret=0;
while(n>0)
{
ret+=n%10;
n/=10;
}
return ret;
}
int dfs(int i,int j,int m,int n,int k)
{
if(i<0||i>=m||j<0||j>=n||(countnum(i)+countnum(j)>k)||vis[i][j]==true)
return 0;
vis[i][j]=true;
//return 1+dfs(i-1,j,m,n,k)+dfs(i,j-1,m,n,k)+dfs(i+1,j,m,n,k)+dfs(i,j+1,m,n,k);
//也可以
return 1+dfs(i+1,j,m,n,k)+dfs(i,j+1,m,n,k);
}
int movingCount(int m, int n, int k) {
vis.assign(m,vector<bool>(n,false));
return dfs(0,0,m,n,k);
}
};
2 bfs
思路: bfs就是利用一个队列,从矩阵的首元素开始(0,0),取对头元素,出队,判断对头元素的上下左右是否合法,这里仍然需要一个vis数组记录某个位置是是否访问过,最后ans++。为方便记录和比较,我们在队列中使用pair(int x ,int y),入对的是坐标
class Solution {
public:
int getnum(int x)
{
int sum=0;
while(x)
{
sum+=x%10;
x/=10;
}
return sum;
}
vector<vector<bool>> vis;
int movingCount(int m, int n, int k) {
// vis.assign(m,vector<bool>(n,false));
vector<vector<bool>> vis(m,vector<bool>(n,false));
int ans=0;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
queue<pair<int,int>> que;
que.push(make_pair(0,0));
ans++;
vis[0][0]=true;
while(!que.empty())
{
auto [x,y]=que.front();
que.pop();
for(int i=0;i<4;i++)
{
x=x+dx[i];
y=y+dy[i];
if(x>=m||x<0||y>=n||y<0||vis[x][y]==true||(getnum(x)+getnum(y))>k)
continue;
que.push(make_pair(x,y));
vis[x][y]=true;
ans++;
}
}
return ans;
}
};