【深度优先搜索】【leetcode】【中等】剑指 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。请问该机器人能够到达多少个格子?

示例 :

输入:m = 2, n = 3, k = 1
输出:3

来源:

剑指 Offer 13. 机器人的运动范围

解题思路:

此题考查的是图的搜索,不管深度优先还是广度优先都是可以的,另外我们可以提前计算每个格子的数位之和,搜索时当和大于k时不能进入。标记访问过的坐标,最后数一下标记坐标的数量即可。

如下图,m=n=20,当k=9时,蓝色区域是可以访问的,橙色区域虽然"和"满足条件但没路径可达,所以也不可访问。

广度优先搜索需要配合队列使用,写起来相对麻烦,而深度优先搜索可以递归调用,代码简洁,所以我采用深度优先搜索,代码如下:

int num(int n) {
    int ret = 0;
    while (n > 0) {
        ret += n % 10;
        n /= 10;
    }
    return ret;
}
void dfs(int data[][101], int m, int n, int x, int y, int k) {
    if (data[x][y] == -1 || data[x][y] > k) {
        return;
    }
    data[x][y] = -1; // 设置访问标记
    if (x > 0) dfs(data, m, n, x-1, y, k);  // 上
    if (x+1 < m) dfs(data, m, n, x+1, y, k);// 下
    if (y > 0) dfs(data, m, n, x, y-1, k);  // 左
    if (y+1 < n) dfs(data, m, n, x, y+1, k);// 右
}
int movingCount(int m, int n, int k){
    int data[101][101] = {0};
    // 提前计算数位之和
    for (int i = 1; i < m; i++) {
        int t = num(i);
        for (int j = 0; j < n; j++) {
            data[i][j] = t;
        }
    }
    for (int j = 1; j < n; j++) {
        int t = num(j);
        for (int i = 0; i < m; i++) {
            data[i][j] += t;
        }
    }
    
    // 深度优先搜索
    dfs(data, m, n, 0, 0, k);
    // 数一下
    int count = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (data[i][j] < 0) count++;
        }
    }
    return count;
}

猜你喜欢

转载自blog.csdn.net/hbuxiaoshe/article/details/114669359