题意分析

  • 给我们一张二维的地图,初始的位置在(0,0),可以往上下左右四个方向进行移动。但是移动需要需要满足如下条件:

    • 不能超过地图的边界
    • 移动的位置的坐标的数位的数字的和不能超过给定的数字

图片说明

思路分析

  • 这个题目我主要用的是BFS和DFS这两个算法进行求解。可以结合这个图进行理解。

图片说明

解法一 BFS

  • 我们知道,对于每一个位置,我们可以选择四个方向进行移动,由于这个题目没有其他特殊的限制,所以我们可以进行广度优先遍历。我们首先将初始的位置保存到一个队列里面,然后从这个队列开始向外进行扩展,当我们扩展之前我们需要判断需要入队的位置是否符合题目的条件,如果满足,那么我们可以直接将这个位置入队。然后继续想之后的位置进行同样的拓展。直到整个队列都为空的。
  • 代码如下
    • 每个位置需要遍历一遍,所以时间复杂度为O(rows*cols)
    • 对于每个位置需要我们存储,所以空间复杂度为O(rows*cols)
class Solution {
public:
    int X[4]={0,0,1,-1};
    int Y[4]={1,-1,0,0};
    bool vis[105][105];  // 用于判断每个位置被访问的情况
// getsum 是获取一个数的数位之和的一个函数
    int getsum(int x){
        int sum=0;
        while(x){
            sum+=x%10;
            x/=10;
        }
        return sum;
    }
// 定义每个状态的结构,就是x和y坐标
    struct node{
        int x,y;
    }Node;
    queue<node> q;
    int movingCount(int threshold, int rows, int cols) {
    // 初始化一个队列,将最开始的点放入整个队列里面
        Node.x=Node.y=0;
        q.push(Node);
        vis[0][0]=true;
        int ans=1;
        while(!q.empty()){
            node now=q.front();
            q.pop();
        // 判断上下左右四个方向是否可行
            for(int i=0;i<4;i++){
                int nowx=now.x+X[i];
                int nowy=now.y+Y[i];
                // 将不符合条件的剔除
                if(nowx>rows-1||nowx<0||nowy>cols-1||nowy<0) continue;
                if(vis[nowx][nowy]||getsum(nowx)+getsum(nowy)>threshold) continue;
                Node.x=nowx,Node.y=nowy;
                ans++;
                vis[nowx][nowy]=true;
                q.push(Node);
            }
        }
        return ans;
    }
};

解法二 DFS

  • 这种解法就是上一个解法的变形,只是写法不一样,其他的实质还是一样的。具体的思路和BFS也是一样的。就是我们不断递归判断四个方向的情况,知道不符合条件即可。不过这种解法也是有缺点的,就是如果递归太深的话会造成爆栈。这个是要注意的。

  • 代码如下

    • 每个位置需要遍历一遍,所以时间复杂度为O(rows*cols)
    • 对于每个位置需要我们存储,所以空间复杂度为O(rows*cols)
      class Solution {
      public:
      int ans=0;
      bool vis[120][120];
      // getsum用来计算某一个数的所有的数位的和
      int getsum(int x){
        int sum=0;
        while(x){
            sum+=x%10;
            x/=10;
        }
        return sum;
      }
      void dfs(int r,int w,int rows,int cols,int threshold){
        // 递归出口
        if(r<0||r>rows-1||w<0||w>cols-1){
            return;
        }
        if(vis[r][w]==true||getsum(r)+getsum(w)>threshold){
            return ;
        }
        // 更新状态
        vis[r][w]=true;
        ans++;
        // 不断递归四个方向
        dfs(r+1,w,rows,cols,threshold);
        dfs(r,w+1,rows,cols,threshold);
        dfs(r-1,w,rows,cols,threshold);
        dfs(r,w-1,rows,cols,threshold);
      }
      int movingCount(int threshold, int rows, int cols) {
        dfs(0,0,rows,cols,threshold);
        return ans;
      }
      };